📄 cpu_s.s
字号:
* if a1 == 0, sys_icache_invalidate_addr modifies only t1. * * Description : * ------------- * Invalidate I cache line containing specified address. * * We bypass the cache operations if CPU is running uncached. * (We assume Config.k0 == K_CacheAttrU is the * only uncached mode used). * * a0 holds the address * a1 != 0 => flush pipeline after the invalidation * * Address MUST be KSEG0/KSEG1 * * Return values : * --------------- * None * ************************************************************************/LEAF(sys_icache_invalidate_addr) MFC0( t1, C0_Config ) andi t1, M_ConfigK0 xori t1, K_CacheAttrU << S_ConfigK0 beq t1, zero, 2f nop la t1, sys_l2cache_enabled lb t1, 0(t1) beq t1, zero, 1f nopSET_MIPS3() SCACHE_ADDR_HIT_WB_INVALIDATE_OP(a0) sync1: ICACHE_ADDR_INVALIDATE_OP(a0,t1)SET_MIPS0()2: bne a1, zero, sys_flush_pipeline nop jr ra nop END(sys_icache_invalidate_addr)/************************************************************************ * * sys_flush_pipeline * Description : * ------------- * * Flush pipeline * * a0 holds the index * * Return values : * --------------- * * None * ************************************************************************/LEAF(sys_flush_pipeline) MFC0( t0, C0_Status ) /* Set STATUS in a well defined state so that we can perform * a controlled eret (one without modifying shadow registers * in case of a MIPS32/MIPS64 release 2 CPU). * * Note that we may end up here due a user application calling * e.g. SYSCON through the application interface. So, STATUS * is not necessarily in a well known state at this point. * * We need to make sure STATUS has the following settings : * * ERL = 0 (so EPC is used rather than ErrorEPC) * BEV = 1 (so shadowsets are not shifted) * IE = 0 (so interrupts are disabled) * KSU = 00 (so that we end up in kernel mode after eret) */ /* First set KSU=00, IE=0 */ ori t1, t0, (M_StatusKSU | M_StatusIE) xori t1, (M_StatusKSU | M_StatusIE) MTC0( t1, C0_Status ) /* Now set BEV */ li t2, M_StatusBEV or t1, t2 MTC0( t1, C0_Status ) /* Finally, clear ERL */ ori t1, M_StatusERL xori t1, M_StatusERL MTC0( t1, C0_Status ) la t1, sys_64bit lb t1, 0(t1) bne t1, zero, 1f nop /* 32 bit CPU */ MFC0( t1, C0_EPC ) /* Store EPC */ /* Now setup EPC and perform eret */ la t2, after_eret32 MTC0( t2, C0_EPC )SET_MIPS3() eretSET_MIPS0()after_eret32 : MTC0( t1, C0_EPC ) /* Restore EPC */ b 2f nop 1: /* 64 bit CPU */SET_MIPS3() DMFC0( t1, C0_EPC ) /* Store EPC */ /* Now setup EPC and perform eret */ la t2, after_eret64 DMTC0( t2, C0_EPC ) eretafter_eret64 : DMTC0( t1, C0_EPC ) /* Restore EPC */SET_MIPS0() 2: /* Restore STATUS and return */ MTC0( t0, C0_Status ) jr ra nopEND(sys_flush_pipeline) /************************************************************************ * * sys_dcache_flush_index * Description : * ------------- * * Flush D cache line containing specified index * * a0 holds the index * * Return values : * --------------- * * None * ************************************************************************/LEAF(sys_dcache_flush_index)SET_MIPS3() cache DCACHE_INDEX_WRITEBACK_INVALIDATE, 0(a0)SET_MIPS0() sync jr ra nop END(sys_dcache_flush_index)/************************************************************************ * * sys_dcache_flush_addr * Note * ------ * This function is called from user2yamon() in application context, * possibly in 64 bit mode and with invalid gp. * sys_dcache_flush_addr modifies only t1. * * Description : * ------------- * Flush D cache line containing specified address. * * We bypass the cache operations if CPU is running uncached. * (We assume Config.k0 == K_CacheAttrU is the * only uncached mode used). * * a0 holds the address * * Address MUST be KSEG0/KSEG1 * * Return values : * --------------- * None * ************************************************************************/LEAF(sys_dcache_flush_addr) MFC0( t1, C0_Config ) andi t1, M_ConfigK0 xori t1, K_CacheAttrU << S_ConfigK0 beq t1, zero, 2f nop la t1, sys_l2cache_enabled lb t1, 0(t1) beq t1, zero, 1f nop /* This secondary cache operation will also flush $D, * so we don't need to flush $D. */SET_MIPS3() cache DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(a0) sync SCACHE_ADDR_HIT_WB_INVALIDATE_OP(a0)SET_MIPS0() b 2f nop1: SET_MIPS3() cache DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(a0)SET_MIPS0()2: sync jr ra lb zero, 0(a0)END(sys_dcache_flush_addr)/************************************************************************ * * sys_scache_flush_index * Description : * ------------- * * Flush L2 cache line containing specified index * * a0 holds the index * * Return values : * --------------- * * None * ************************************************************************/LEAF( sys_scache_flush_index )SET_MIPS3() SCACHE_INDEX_WRITEBACK_INVALIDATE_OP(a0)SET_MIPS0() sync jr ra nop END( sys_scache_flush_index )/************************************************************************ * * sys_enable_int * Description : * ------------- * * Enable interrupt: set IE in CP0-status. * * Return values : * --------------- * * None * ************************************************************************/LEAF(sys_enable_int) MFC0( v0, C0_Status) or v0, M_StatusIE MTC0( v0, C0_Status) j ra nopEND(sys_enable_int)/************************************************************************ * * sys_disable_int * Description : * ------------- * * UINT32 sys_disable_int( void ) * * Disable interrupt: clear IE in CP0-status. * * Return values : * --------------- * * Old IE bit * ************************************************************************/LEAF(sys_disable_int) MFC0( v0, C0_Status) li t0, ~M_StatusIE nop and v1, v0, t0 MTC0( v1, C0_Status) li t0, M_StatusIE j ra and v0, t0END(sys_disable_int)/************************************************************************ * * sys_enable_int_mask * Description : * ------------- * * Enable specific interrupt: set IM[x] bit in CP0-status. * * Return values : * --------------- * * None * ************************************************************************/LEAF(sys_enable_int_mask) MFC0( v0, C0_Status) li t0, 1 addiu a0, S_StatusIM sllv t0, t0, a0 or v0, t0 MTC0( v0, C0_Status) j ra nopEND(sys_enable_int_mask)/************************************************************************ * * sys_disable_int_mask * Description : * ------------- * * Disable specific interrupt: set IM[x] bit in CP0-status. * * Return values : * --------------- * * None * ************************************************************************/LEAF(sys_disable_int_mask) MFC0( v0, C0_Status) li t0, 1 addiu a0, S_StatusIM sllv t0, t0, a0 li t1, 0xffffffff xor t0, t1 and v0, t0 MTC0( v0, C0_Status) j ra nopEND(sys_disable_int_mask) /************************************************************************ * * sys_cpu_k0_config * Description : * ------------- * * Configure K0 field of CP0 CONFIG register * * a0 holds the requested K0 setting * * Return values : * --------------- * * None * ************************************************************************/LEAF( sys_cpu_k0_config ) /* Reserve space on stack */ addiu sp, -8*4 /* Store registers */ sw ra, 0(sp) sw s0, 4(sp) sw s1, 8(sp) /* Copy registers to preserved registers */ move s0, a0 /* Disable interrupts */ MFC0( s1, C0_Status ) li t0, ~M_StatusIE and t0, s1 MTC0( t0, C0_Status ) /* Flush D-Cache */ addiu sp, -4*4 la t0, sys_dcache_flush_all jal t0 nop addiu sp, 4*4 /* Invalidate I-Cache */ addiu sp, -4*4 la t0, sys_icache_invalidate_all jal t0 nop addiu sp, 4*4 /* Shift to uncached */ la t0, sys_cpu_k0_config_uncached li t1, KSEG1BASE or t0, t1 jr t0 nopsys_cpu_k0_config_uncached : /* Set K0 field */ sll s0, S_ConfigK0 MFC0( t1, C0_Config ) li t0, ~M_ConfigK0 and t1, t0 or t1, s0 MTC0( t1, C0_Config ) /* Restore CP0 STATUS */ MTC0( s1, C0_Status ) /* Restore registers */ lw ra, 0(sp) lw s0, 4(sp) lw s1, 8(sp) jr ra addiu sp, 8*4 END( sys_cpu_k0_config ) /************************************************************************ * * sys_sync * Description : * ------------- * * Issue "sync" instruction * * Return values : * --------------- * * None * ************************************************************************/LEAF( sys_sync ) sync jr ra nopEND( sys_sync )/************************************************************************ * * sys_fpu_enable * Description : * ------------- * * Enable FPU * ************************************************************************/LEAF( sys_fpu_enable ) /* Enable FPU */ MFC0( t0, C0_Status ) li t1, M_StatusCU1 or t0, t1 MTC0( t0, C0_Status ) /* Set up FPU Control/Status register */ li t0, M_FCSRFS /* Set FS (flush to zero) bit */ ctc1 t0, C1_FCSR jr ra nop END( sys_fpu_enable ) /******* Functions for access to CP1 (FPU) registers ******/ /************************************************************************ *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -