⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu_asm.s

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 S
📖 第 1 页 / 共 2 页
字号:
/*  * TODO:  *       Context_switch needs to only save callee save registers *       I think this means can skip:    r1, r2, r19-29, r31 *       Ref:     p 3-2 of Procedure Calling Conventions Manual *       This should be #ifndef DEBUG so that debugger has *       accurate visibility into all registers * *  This file contains the assembly code for the HPPA implementation *  of RTEMS. * *  COPYRIGHT (c) 1994,95 by Division Incorporated * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * *  $Id: cpu_asm.S,v 1.3.2.1 2003/09/04 18:47:25 joel Exp $ */#include <rtems/score/hppa.h>#include <rtems/score/cpu_asm.h>#include <rtems/score/cpu.h>#include <rtems/score/offsets.h>#if 0#define TEXT_SEGMENT \        .SPACE  $TEXT$          !\        .SUBSPA $CODE$#define RO_SEGMENT \        .SPACE  $TEXT$          !\        .SUBSPA $lit$#define DATA_SEGMENT \        .SPACE  $PRIVATE$          !\        .SUBSPA $data$#define BSS_SEGMENT \        .SPACE  $PRIVATE$          !\        .SUBSPA $bss$#else#define TEXT_SEGMENT .text #define RO_SEGMENT .rodata #define DATA_SEGMENT .data#define BSS_SEGMENT .bss#endif  #if 0	.SPACE $PRIVATE$	.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31	.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82	.SPACE $TEXT$	.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44	.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY	.SPACE $TEXT$	.SUBSPA $CODE$#endif	TEXT_SEGMENT/* * Special register usage for context switch and interrupts * Stay away from %cr28 which is used for TLB misses on 72000 */isr_arg0           .reg    %cr24isr_r9             .reg    %cr25isr_r8             .reg    %cr26/* * Interrupt stack frame looks like this * *  offset                                   item * ----------------------------------------------------------------- *   INTEGER_CONTEXT_OFFSET             Context_Control *   FP_CONTEXT_OFFSET                  Context_Control_fp * * It is padded out to a multiple of 64 *//*PAGE^L *  void _Generic_ISR_Handler() * *  This routine provides the RTEMS interrupt management. * *   We jump here from the interrupt vector. *   The HPPA hardware has done some stuff for us: *       PSW saved in IPSW *       PSW set to 0 *       PSW[E] set to default (0) *       PSW[M] set to 1 iff this is HPMC * *       IIA queue is frozen (since PSW[Q] is now 0) *       privilege level promoted to 0 *       IIR, ISR, IOR potentially updated if PSW[Q] was 1 at trap *       registers GR  1,8,9,16,17,24,25 copied to shadow regs *                 SHR 0 1 2  3  4  5  6 * *   Our vector stub (in the BSP) MUST have done the following:   * *   a) Saved the original %r9 into %isr_r9 (%cr25) *   b) Placed the vector number in %r9 *   c) Was allowed to also destroy $isr_r8 (%cr26), *      but the stub was NOT allowed to destroy any other registers. * *   The typical stub sequence (in the BSP) should look like this: * *   a)     mtctl   %r9,isr_r9     ; (save r9 in cr25) *   b)     ldi     vector,%r9     ; (load constant vector number in r9) *   c)     mtctl   %r8,isr_r8     ; (save r8 in cr26) *   d)     ldil    L%MY_BSP_first_level_interrupt_handler,%r8 *   e)     ldo     R%MY_BSP_first_level_interrupt_handler(%r8),%r8 *                                 ; (point to BSP raw handler table) *   f)     ldwx,s  %r9(%r8),%r8   ; (load value from raw handler table) *   g)     bv      0(%r8)         ; (call raw handler: _Generic_ISR_Handler) *   h)     mfctl   isr_r8,%r8     ; (restore r8 from cr26 in delay slot) * *   Optionally, steps (c) thru (h) _could_ be replaced with a single *          bl,n    _Generic_ISR_Handler,%r0 * * */	.EXPORT _Generic_ISR_Handler,ENTRY,PRIV_LEV=0_Generic_ISR_Handler:	.PROC	.CALLINFO FRAME=0,NO_CALLS	.ENTRY        mtctl     arg0, isr_arg0/* * save interrupt state */        mfctl     ipsw, arg0        stw       arg0, IPSW_OFFSET(sp)        mfctl     iir, arg0        stw       arg0, IIR_OFFSET(sp)        mfctl     ior, arg0        stw       arg0, IOR_OFFSET(sp)        mfctl     pcoq, arg0        stw       arg0, PCOQFRONT_OFFSET(sp)	mtctl	  %r0, pcoq        mfctl     pcoq, arg0        stw       arg0, PCOQBACK_OFFSET(sp)        mfctl     %sar, arg0        stw       arg0, SAR_OFFSET(sp)/* * Build an interrupt frame to hold the contexts we will need. * We have already saved the interrupt items on the stack * * At this point the following registers are damaged wrt the interrupt *  reg    current value        saved value * ------------------------------------------------ *  arg0   scratch               isr_arg0  (cr24) *  r9     vector number         isr_r9    (cr25) * * Point to beginning of integer context and * save the integer context */        stw         %r1,R1_OFFSET(sp)        stw         %r2,R2_OFFSET(sp)        stw         %r3,R3_OFFSET(sp)        stw         %r4,R4_OFFSET(sp)        stw         %r5,R5_OFFSET(sp)        stw         %r6,R6_OFFSET(sp)        stw         %r7,R7_OFFSET(sp)        stw         %r8,R8_OFFSET(sp)/* * skip r9 */        stw         %r10,R10_OFFSET(sp)        stw         %r11,R11_OFFSET(sp)        stw         %r12,R12_OFFSET(sp)        stw         %r13,R13_OFFSET(sp)        stw         %r14,R14_OFFSET(sp)        stw         %r15,R15_OFFSET(sp)        stw         %r16,R16_OFFSET(sp)        stw         %r17,R17_OFFSET(sp)        stw         %r18,R18_OFFSET(sp)        stw         %r19,R19_OFFSET(sp)        stw         %r20,R20_OFFSET(sp)        stw         %r21,R21_OFFSET(sp)        stw         %r22,R22_OFFSET(sp)        stw         %r23,R23_OFFSET(sp)        stw         %r24,R24_OFFSET(sp)        stw         %r25,R25_OFFSET(sp)/* * skip arg0 */        stw         %r27,R27_OFFSET(sp)        stw         %r28,R28_OFFSET(sp)        stw         %r29,R29_OFFSET(sp)        stw         %r30,R30_OFFSET(sp)        stw         %r31,R31_OFFSET(sp)/* Now most registers are available since they have been saved * * The following items are currently wrong in the integer context *  reg    current value        saved value * ------------------------------------------------ *  arg0   scratch               isr_arg0  (cr24) *  r9     vector number         isr_r9    (cr25) * * Fix them */         mfctl      isr_arg0,%r3         stw        %r3,ARG0_OFFSET(sp)         mfctl      isr_r9,%r3         stw        %r3,R9_OFFSET(sp)/* * At this point we are done with isr_arg0, and isr_r9 control registers * * Prepare to re-enter virtual mode * We need Q in case the interrupt handler enables interrupts */        ldil      L%CPU_PSW_DEFAULT, arg0        ldo       R%CPU_PSW_DEFAULT(arg0), arg0        mtctl     arg0, ipsw/* * Now jump to "rest_of_isr_handler" with the rfi * We are assuming the space queues are all correct already */	ldil 	  L%rest_of_isr_handler, arg0	ldo	  R%rest_of_isr_handler(arg0), arg0	mtctl	  arg0, pcoq	ldo	  4(arg0), arg0	mtctl	  arg0, pcoq        rfi	nop/* * At this point we are back in virtual mode and all our *  normal addressing is once again ok. * *  It is now ok to take an exception or trap */rest_of_isr_handler:/* * Point to beginning of float context and * save the floating point context -- doing whatever patches are necessary */        .call ARGW0=GR        bl          _CPU_Save_float_context,%r2        ldo         FP_CONTEXT_OFFSET(sp),arg0/* * save the ptr to interrupt frame as an argument for the interrupt handler */        copy        sp, arg1/* * Advance the frame to point beyond all interrupt contexts (integer & float) * this also includes the pad to align to 64byte stack boundary */        ldo         CPU_INTERRUPT_FRAME_SIZE(sp), sp/* *    r3  -- &_ISR_Nest_level *    r5  -- value _ISR_Nest_level *    r4  -- &_Thread_Dispatch_disable_level *    r6  -- value _Thread_Dispatch_disable_level *    r9  -- vector number */ 	.import   _ISR_Nest_level,data	ldil	  L%_ISR_Nest_level,%r3	ldo	  R%_ISR_Nest_level(%r3),%r3	ldw	  0(%r3),%r5	.import   _Thread_Dispatch_disable_level,data	ldil	  L%_Thread_Dispatch_disable_level,%r4	ldo	  R%_Thread_Dispatch_disable_level(%r4),%r4	ldw	  0(%r4),%r6/* * increment interrupt nest level counter.  If outermost interrupt * switch the stack and squirrel away the previous sp. */        addi      1,%r5,%r5        stw       %r5, 0(%r3)/* * compute and save new stack (with frame) * just in case we are nested -- simpler this way */        comibf,=  1,%r5,stack_done        ldo       128(sp),%r7/* * Switch to interrupt stack allocated by the interrupt manager (intr.c) */        .import   _CPU_Interrupt_stack_low,data	ldil	  L%_CPU_Interrupt_stack_low,%r7	ldw	  R%_CPU_Interrupt_stack_low(%r7),%r7        ldo       128(%r7),%r7stack_done:/* * save our current stack pointer where the "old sp" is supposed to be */        stw       sp, -4(%r7)/* * and switch stacks (or advance old stack in nested case) */        copy      %r7, sp/* * increment the dispatch disable level counter. */        addi      1,%r6,%r6        stw       %r6, 0(%r4)/* * load address of user handler * Note:  No error checking is done, it is assumed that the *        vector table contains a valid address or a stub *        spurious handler. */        .import   _ISR_Vector_table,data	ldil	  L%_ISR_Vector_table,%r8	ldo	  R%_ISR_Vector_table(%r8),%r8        ldw       0(%r8),%r8        ldwx,s    %r9(%r8),%r8/* * invoke user interrupt handler * Interrupts are currently disabled, as per RTEMS convention * The handler has the option of re-enabling interrupts * NOTE:  can not use 'bl' since it uses "pc-relative" addressing *    and we are using a hard coded address from a table *  So... we fudge r2 ourselves (ala dynacall) *  arg0 = vector number, arg1 = ptr to rtems_interrupt_frame */        copy      %r9, %r26        .call  ARGW0=GR, ARGW1=GR        blr       %r0, rp        bv,n      0(%r8)post_user_interrupt_handler:/* * Back from user handler(s) * Disable external interrupts (since the interrupt handler could * have turned them on) and return to the interrupted task stack (assuming * (_ISR_Nest_level == 0) */        rsm        HPPA_PSW_I + HPPA_PSW_R, %r0        ldw        -4(sp), sp/* *    r3  -- (most of) &_ISR_Nest_level *    r5  -- value _ISR_Nest_level *    r4  -- (most of) &_Thread_Dispatch_disable_level *    r6  -- value _Thread_Dispatch_disable_level *    r7  -- (most of) &_ISR_Signals_to_thread_executing *    r8  -- value _ISR_Signals_to_thread_executing */ 	.import   _ISR_Nest_level,data	ldil	  L%_ISR_Nest_level,%r3	ldw	  R%_ISR_Nest_level(%r3),%r5	.import   _Thread_Dispatch_disable_level,data	ldil	  L%_Thread_Dispatch_disable_level,%r4	ldw	  R%_Thread_Dispatch_disable_level(%r4),%r6	.import    _ISR_Signals_to_thread_executing,data	ldil	   L%_ISR_Signals_to_thread_executing,%r7/* * decrement isr nest level */	addi      -1, %r5, %r5        stw       %r5, R%_ISR_Nest_level(%r3)/* * decrement dispatch disable level counter and, if not 0, go on */        addi       -1,%r6,%r6        comibf,=   0,%r6,isr_restore        stw        %r6, R%_Thread_Dispatch_disable_level(%r4)/* * check whether or not a context switch is necessary

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -