Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:24

0001 /*
0002  *  This file contains all assembly code for the
0003  *  LM32 implementation of RTEMS.
0004  *
0005  *  Derived from no_cpu/cpu_asm.S, copyright (c) 1989-1999,
0006  *    On-Line Applications Research Corporation (OAR).
0007  *
0008  *  The license and distribution terms for this file may be
0009  *  found in the file LICENSE in this distribution or at
0010  *  http://www.rtems.org/license/LICENSE.
0011  *
0012  *  Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
0013  *  Micro-Research Finland Oy
0014  *
0015  *  Michael Walle <michael@walle.cc>, 2009
0016  */
0017 
0018 #ifdef HAVE_CONFIG_H
0019 #include "config.h"
0020 #endif
0021 
0022 #include <rtems/asm.h>
0023 #include <rtems/score/cpu_asm.h>
0024 
0025 /*  void _CPU_Context_switch(run_context, heir_context)
0026  *
0027  *  This routine performs a normal non-FP context switch.
0028  *
0029  *  LM32 Specific Information:
0030  *
0031  *  Saves/restores all callee-saved general purpose registers as well as
0032  *  the stack pointer, return address and interrupt enable status register
0033  *  to/from the context.
0034  *
0035  */
0036     .globl _CPU_Context_switch
0037 _CPU_Context_switch:
0038     sw      (r1+0), r11   /* r1 is the first argument */
0039     sw      (r1+4), r12
0040     sw      (r1+8), r13
0041     sw      (r1+12), r14
0042     sw      (r1+16), r15
0043     sw      (r1+20), r16
0044     sw      (r1+24), r17
0045     sw      (r1+28), r18
0046     sw      (r1+32), r19
0047     sw      (r1+36), r20
0048     sw      (r1+40), r21
0049     sw      (r1+44), r22
0050     sw      (r1+48), r23
0051     sw      (r1+52), r24
0052     sw      (r1+56), r25
0053     sw      (r1+60), gp
0054     sw      (r1+64), fp
0055     sw      (r1+68), sp
0056     sw      (r1+72), ra
0057     rcsr    r3, IE
0058     sw      (r1+76), r3
0059     .extern _exception_stack_frame
0060     mvhi    r3, hi(_exception_stack_frame)
0061     ori     r3, r3, lo(_exception_stack_frame)
0062     lw      r4, (r3+0)
0063     be      r4, r0, 2f
0064 1:
0065     lw      r5, (r4+44)
0066     sw      (r3+0), r0
0067     bi      3f
0068 2:
0069     mvhi    r5, hi(_Thread_Dispatch)
0070     ori     r5, r5, lo(_Thread_Dispatch)
0071 3:
0072     sw      (r1+80), r5
0073 
0074 _CPU_Context_switch_restore:
0075     lw      r11, (r2+0)   /* r2 is the second argument */
0076     lw      r12, (r2+4)
0077     lw      r13, (r2+8)
0078     lw      r14, (r2+12)
0079     lw      r15, (r2+16)
0080     lw      r16, (r2+20)
0081     lw      r17, (r2+24)
0082     lw      r18, (r2+28)
0083     lw      r19, (r2+32)
0084     lw      r20, (r2+36)
0085     lw      r21, (r2+40)
0086     lw      r22, (r2+44)
0087     lw      r23, (r2+48)
0088     lw      r24, (r2+52)
0089     lw      r25, (r2+56)
0090     lw      gp, (r2+60)
0091     lw      fp, (r2+64)
0092     lw      sp, (r2+68)
0093     lw      ra, (r2+72)
0094     lw      r3, (r2+76)
0095     wcsr    IE, r3
0096     ret
0097 
0098 /*
0099  *  _CPU_Context_restore
0100  *
0101  *  This routine is generally used only to restart self in an
0102  *  efficient manner.  It may simply be a label in _CPU_Context_switch.
0103  *
0104  *  LM32 Specific Information:
0105  *
0106  *  Moves argument #1 to #2 and branches to the restore part of the
0107  *  context switch code above.
0108  */
0109     .globl _CPU_Context_restore
0110 _CPU_Context_restore:
0111     mv      r2, r1
0112     bi      _CPU_Context_switch_restore
0113 
0114 /*  void _ISR_Handler()
0115  *
0116  *  This routine provides the RTEMS interrupt management.
0117  *
0118  *  LM32 Specific Information:
0119  *
0120  *  Saves all the caller-saved general purpose registers as well as the
0121  *  return address, exception return address and breakpoint return address
0122  *  (the latter may be unnecessary) onto the stack, which is either the task
0123  *  stack (in case of a interrupted task) or the interrupt stack (if an
0124  *  interrupt was interrupted).
0125  *  After that, it figures out the pending interrupt with the highest
0126  *  priority and calls the main ISR handler written in C, which in turn
0127  *  handles interrupt nesting, software interrupt stack setup etc and
0128  *  finally calls the user ISR.
0129  *  At the end the saved registers are restored.
0130  *
0131  */
0132 
0133     .globl  _ISR_Handler
0134 _ISR_Handler:
0135     xor      r0, r0, r0
0136     addi     sp, sp, -52
0137     sw       (sp+4), r1
0138     sw       (sp+8), r2
0139     sw       (sp+12), r3
0140     sw       (sp+16), r4
0141     sw       (sp+20), r5
0142     sw       (sp+24), r6
0143     sw       (sp+28), r7
0144     sw       (sp+32), r8
0145     sw       (sp+36), r9
0146     sw       (sp+40), r10
0147     sw       (sp+44), ra
0148     sw       (sp+48), ea
0149     sw       (sp+52), ba
0150 
0151     /*
0152      * Scan through IP & IM bits starting from LSB until irq vector is
0153      * found. The vector is stored in r1, which is the first argument for
0154      * __ISR_Handler.
0155      */
0156     rcsr    r2, IP
0157     rcsr    r3, IM
0158     mv      r1, r0        /* r1: counter for the vector number */
0159     and     r2, r2, r3    /* r2: pending irqs, which are enabled */
0160     mvi     r3, 1         /* r3: register for the walking 1 */
0161     /*
0162      * If r2 is zero, there was no interrupt.
0163      * This should never happen!
0164      */
0165     be      r2, r0, exit_isr
0166 find_irq:
0167     and     r4, r2, r3
0168     bne     r4, r0, found_irq
0169     sli     r3, r3, 1
0170     addi    r1, r1, 1
0171     bi      find_irq
0172 
0173 found_irq:
0174     /*
0175      * Call __ISR_Handler for further processing.
0176      * r1 is the vector number, calculated above
0177      * r2 is the pointer to the CPU_Interrupt_frame
0178      */
0179     addi    r2, sp, 4
0180 
0181     .extern __ISR_Handler
0182     mvhi    r3, hi(__ISR_Handler)
0183     ori     r3, r3, lo(__ISR_Handler)
0184     call    r3
0185 
0186 exit_isr:
0187     /* Restore the saved registers */
0188     lw      r1, (sp+4)
0189     lw      r2, (sp+8)
0190     lw      r3, (sp+12)
0191     lw      r4, (sp+16)
0192     lw      r5, (sp+20)
0193     lw      r6, (sp+24)
0194     lw      r7, (sp+28)
0195     lw      r8, (sp+32)
0196     lw      r9, (sp+36)
0197     lw      r10, (sp+40)
0198     lw      ra, (sp+44)
0199     lw      ea, (sp+48)
0200     lw      ba, (sp+52)
0201     addi    sp, sp, 52
0202     eret
0203