📄 cpu_asm.s
字号:
/* determine if an interrupt generated this exception */ mfc0 k0,C0_CAUSE and k1,k0,CAUSE_EXCMASK bnez k1,_ISR_Handler_prom_exit /* not an external interrupt, pass exception to Monitor */ mfc0 k1,C0_SR and k0,k1 and k0,CAUSE_IPMASK beq k0,zero,_ISR_Handler_quick_exit /* external interrupt not enabled, ignore */ nop /* * save some or all context on stack * may need to save some special interrupt information for exit * * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) * if ( _ISR_Nest_level == 0 ) * switch to software interrupt stack * #endif */#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) lint t0,_ISR_Nest_level beq t0, zero, _ISR_Handler_1 nop /* switch stacks */ _ISR_Handler_1:#else lint t0,_ISR_Nest_level#endif /* * _ISR_Nest_level++; */ addi t0,t0,1 sint t0,_ISR_Nest_level /* * _Thread_Dispatch_disable_level++; */ lint t1,_Thread_Dispatch_disable_level addi t1,t1,1 sint t1,_Thread_Dispatch_disable_level#if 0 nop j _ISR_Handler_4 nop /* * while ( interrupts_pending(cause_reg) ) { * vector = BITFIELD_TO_INDEX(cause_reg); * (*_ISR_Vector_table[ vector ])( vector ); * } */_ISR_Handler_2:/* software interrupt priorities can be applied here */ li t1,-1/* convert bit field into interrupt index */_ISR_Handler_3: andi t2,t0,1 addi t1,1 beql t2,zero,_ISR_Handler_3 dsrl t0,1 li t1,7 dsll t1,3 /* convert index to byte offset (*8) */ la t3,_ISR_Vector_table intadd t1,t3 lint t1,(t1) jalr t1 nop j _ISR_Handler_5 nop_ISR_Handler_4: mfc0 t0,C0_CAUSE andi t0,CAUSE_IPMASK bne t0,zero,_ISR_Handler_2 dsrl t0,t0,8_ISR_Handler_5:#else nop li t1,7 dsll t1,t1,SZ_INT_POW2 la t3,_ISR_Vector_table intadd t1,t3 lint t1,(t1) jalr t1 nop#endif /* * --_ISR_Nest_level; */ lint t2,_ISR_Nest_level addi t2,t2,-1 sint t2,_ISR_Nest_level /* * --_Thread_Dispatch_disable_level; */ lint t1,_Thread_Dispatch_disable_level addi t1,t1,-1 sint t1,_Thread_Dispatch_disable_level /* * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level ) * goto the label "exit interrupt (simple case)" */ or t0,t2,t1 bne t0,zero,_ISR_Handler_exit nop /* * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) * restore stack * #endif * * if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing ) * goto the label "exit interrupt (simple case)" */ lint t0,_Context_Switch_necessary lint t1,_ISR_Signals_to_thread_executing or t0,t0,t1 beq t0,zero,_ISR_Handler_exit nop /* * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch */ jal _Thread_Dispatch nop /* * prepare to get out of interrupt * return from interrupt (maybe to _ISR_Dispatch) * * LABEL "exit interrupt (simple case): * prepare to get out of interrupt * return from interrupt */_ISR_Handler_exit: ld ra,32(sp) stackadd sp,sp,40/* restore interrupt context from stack */ lreg k0, R_MDLO*R_SZ(sp) mtlo k0 lreg k0, R_MDHI*R_SZ(sp) lreg a2, R_A2*R_SZ(sp) mthi k0 lreg a3, R_A3*R_SZ(sp) lreg t0, R_T0*R_SZ(sp) lreg t1, R_T1*R_SZ(sp) lreg t2, R_T2*R_SZ(sp) lreg t3, R_T3*R_SZ(sp) lreg t4, R_T4*R_SZ(sp) lreg t5, R_T5*R_SZ(sp) lreg t6, R_T6*R_SZ(sp) lreg t7, R_T7*R_SZ(sp) lreg t8, R_T8*R_SZ(sp) lreg t9, R_T9*R_SZ(sp) lreg gp, R_GP*R_SZ(sp) lreg fp, R_FP*R_SZ(sp) lreg ra, R_RA*R_SZ(sp) lreg a0, R_A0*R_SZ(sp) lreg a1, R_A1*R_SZ(sp) lreg v1, R_V1*R_SZ(sp) lreg v0, R_V0*R_SZ(sp) .set noat lreg AT, R_AT*R_SZ(sp) .set at stackadd sp,sp,EXCP_STACK_SIZE /* store ra on the stack */#if USE_IDTKIT/* we handled exception, so return non-zero value */ li v0,1#endif_ISR_Handler_quick_exit:#ifdef USE_IDTKIT j ra#else eret#endif nop_ISR_Handler_prom_exit:#ifdef CPU_R3000 la k0, (R_VEC+((48)*8))#endif#ifdef CPU_R4000 la k0, (R_VEC+((112)*8)) /* R4000 Sim's location is different */#endif j k0 nop .set reorderENDFRAME(_ISR_Handler)FRAME(mips_enable_interrupts,sp,0,ra) mfc0 t0,C0_SR /* get status reg */ nop or t0,t0,a0 mtc0 t0,C0_SR /* save updated status reg */ j ra nopENDFRAME(mips_enable_interrupts)FRAME(mips_disable_interrupts,sp,0,ra) mfc0 v0,C0_SR /* get status reg */ li t1,SR_IMASK /* t1 = load interrupt mask word */ not t0,t1 /* t0 = ~t1 */ and t0,v0 /* clear imask bits */ mtc0 t0,C0_SR /* save status reg */ and v0,t1 /* mask return value (only return imask bits) */ jr ra nopENDFRAME(mips_disable_interrupts)FRAME(mips_enable_global_interrupts,sp,0,ra) mfc0 t0,C0_SR /* get status reg */ nop ori t0,SR_IE mtc0 t0,C0_SR /* save updated status reg */ j ra nopENDFRAME(mips_enable_global_interrupts)FRAME(mips_disable_global_interrupts,sp,0,ra) li t1,SR_IE mfc0 t0,C0_SR /* get status reg */ not t1 and t0,t1 mtc0 t0,C0_SR /* save updated status reg */ j ra nopENDFRAME(mips_disable_global_interrupts)/* return the value of the status register in v0. Used for debugging */FRAME(mips_get_sr,sp,0,ra) mfc0 v0,C0_SR j ra nopENDFRAME(mips_get_sr)FRAME(mips_break,sp,0,ra)#if 1 break 0x0 j mips_break#else j ra#endif nopENDFRAME(mips_break)/*PAGE * * _CPU_Internal_threads_Idle_thread_body * * NOTES: * * 1. This is the same as the regular CPU independent algorithm. * * 2. If you implement this using a "halt", "idle", or "shutdown" * instruction, then don't forget to put it in an infinite loop. * * 3. Be warned. Some processors with onboard DMA have been known * to stop the DMA if the CPU were put in IDLE mode. This might * also be a problem with other on-chip peripherals. So use this * hook with caution. */FRAME(_CPU_Thread_Idle_body,sp,0,ra) wait /* enter low power mode */ j _CPU_Thread_Idle_body nopENDFRAME(_CPU_Thread_Idle_body)#define VEC_CODE_LENGTH 10*4/****************************************************************************** init_exc_vecs() - moves the exception code into the addresses** reserved for exception vectors**** UTLB Miss exception vector at address 0x80000000**** General exception vector at address 0x80000080**** RESET exception vector is at address 0xbfc00000*****************************************************************************/#define INITEXCFRM ((2*4)+4) /* ra + 2 arguments */FRAME(init_exc_vecs,sp,0,ra)/* This code yanked from SIM */#if defined(CPU_R3000) .set noreorder la t1,exc_utlb_code la t2,exc_norm_code li t3,UT_VEC li t4,E_VEC li t5,VEC_CODE_LENGTH1: lw t6,0(t1) lw t7,0(t2) sw t6,0(t3) sw t7,0(t4) addiu t1,4 addiu t3,4 addiu t4,4 subu t5,4 bne t5,zero,1b addiu t2,4 move t5,ra # assumes clear_cache doesnt use t5 li a0,UT_VEC jal clear_cache li a1,VEC_CODE_LENGTH nop li a0,E_VEC jal clear_cache li a1,VEC_CODE_LENGTH move ra,t5 # restore ra j ra nop .set reorder#endif#if defined(CPU_R4000) .set reorder move t5,ra # assumes clear_cache doesnt use t5 /* TLB exception vector */ la t1,exc_tlb_code li t2,T_VEC |K1BASE li t3,VEC_CODE_LENGTH1: lw t6,0(t1) addiu t1,4 subu t3,4 sw t6,0(t2) addiu t2,4 bne t3,zero,1b li a0,T_VEC li a1,VEC_CODE_LENGTH jal clear_cache la t1,exc_xtlb_code li t2,X_VEC |K1BASE li t3,VEC_CODE_LENGTH1: lw t6,0(t1) addiu t1,4 subu t3,4 sw t6,0(t2) addiu t2,4 bne t3,zero,1b /* extended TLB exception vector */ li a0,X_VEC li a1,VEC_CODE_LENGTH jal clear_cache /* cache error exception vector */ la t1,exc_cache_code li t2,C_VEC |K1BASE li t3,VEC_CODE_LENGTH1: lw t6,0(t1) addiu t1,4 subu t3,4 sw t6,0(t2) addiu t2,4 bne t3,zero,1b li a0,C_VEC li a1,VEC_CODE_LENGTH jal clear_cache /* normal exception vector */ la t1,exc_norm_code li t2,E_VEC |K1BASE li t3,VEC_CODE_LENGTH1: lw t6,0(t1) addiu t1,4 subu t3,4 sw t6,0(t2) addiu t2,4 bne t3,zero,1b li a0,E_VEC li a1,VEC_CODE_LENGTH jal clear_cache move ra,t5 # restore ra j ra#endifENDFRAME(init_exc_vecs)#if defined(CPU_R4000)FRAME(exc_tlb_code,sp,0,ra)#ifdef CPU_R3000 la k0, (R_VEC+((48)*8))#endif#ifdef CPU_R4000 la k0, (R_VEC+((112)*8)) /* R4000 Sim's location is different */#endif j k0 nopENDFRAME(exc_tlb_code)FRAME(exc_xtlb_code,sp,0,ra)#ifdef CPU_R3000 la k0, (R_VEC+((48)*8))#endif#ifdef CPU_R4000 la k0, (R_VEC+((112)*8)) /* R4000 Sim's location is different */#endif j k0 nopENDFRAME(exc_xtlb_code)FRAME(exc_cache_code,sp,0,ra)#ifdef CPU_R3000 la k0, (R_VEC+((48)*8))#endif#ifdef CPU_R4000 la k0, (R_VEC+((112)*8)) /* R4000 Sim's location is different */#endif j k0 nopENDFRAME(exc_cache_code)FRAME(exc_norm_code,sp,0,ra) la k0, _ISR_Handler /* generic external int hndlr */ j k0 nop subu sp, EXCP_STACK_SIZE /* set up local stack frame */ENDFRAME(exc_norm_code)#endif/****************************************************************************** enable_int(mask) - enables interrupts - mask is positioned so it only** needs to be or'ed into the status reg. This** also does some other things !!!! caution should** be used if invoking this while in the middle** of a debugging session where the client may have** nested interrupts.******************************************************************************/FRAME(enable_int,sp,0,ra) .set noreorder mfc0 t0,C0_SR or a0,1 or t0,a0 mtc0 t0,C0_SR j ra nop .set reorderENDFRAME(enable_int)/******************************************************************************* disable_int(mask) - disable the interrupt - mask is the complement** of the bits to be cleared - i.e. to clear ext int** 5 the mask would be - 0xffff7fff******************************************************************************/FRAME(disable_int,sp,0,ra) .set noreorder mfc0 t0,C0_SR nop and t0,a0 mtc0 t0,C0_SR j ra nopENDFRAME(disable_int)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -