📄 cpu_support.s
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.01.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* * cpu_support.S (VR5500) * Device-Dependent CPU Operation */#define _in_asm_source_#include <machine.h>#include <tk/errno.h>#include <tk/sysdef.h>#include <tk/asm.h>#include <sys/sysinfo.h>#include "config.h"#include "cpu_conf.h"#include "isysconf.h"#include "tkdev_conf.h"#include "offset.h"/* * IMPORT declaration of external variables * .extern declaration indicates that the 'gp' register is properly used * when the program is assembled. */ .extern Csym(ctxtsk), 4 .extern Csym(schedtsk), 4 .extern Csym(lowpow_discnt), 4 .extern Csym(int_stack_top), 4 .extern Csym(svc_call_limit), 4#if TA_FPU .extern Csym(fpu_ctxtsk), 4#endif/* ------------------------------------------------------------------------ *//* * Dispatcher * dispatch_to_schedtsk: * Throw away the current contexts and forcibly dispatch to * 'schedtsk.' * Called directly by the jump order but do not return. * Called on the undefined stack state (undefined 'ssp'). * Called on the interrupt disable state. * _dispatch_entry: * Normal dispatch processing. Called by the delayed interrupt. * * Contexts to save * Save registers except for 'ssp' to a stack. Save 'ssp' to TCB. * * +---------------+ * ssp -> | hi | * +8 | lo | * +16 | at | * +24 | v0-v1 | * +40 | a0-a3 | * +72 | t0-t7 | * +136 | s0-s7 | * +200 | fp | * +208 | ra | * +216 | gp | * +---------------+ - * +224 | t8 | | * +232 | t9 | | * +240 | EPC | | Move from interrupt * +248 | PSR||taskmode | High:PSR Low:taskmode | stack * +---------------+ | * +256 | usp | Only RNG 1-3 | * +---------------+ - */ /* Temporal stack used when 'dispatch_to_schedtsk' is called */#define TMP_STACK_SZ (8*1024)#define TMP_STACK_TOP (tmp_stack + TMP_STACK_SZ) .lcomm tmp_stack, TMP_STACK_SZ .text .balign 4 .globl Csym(dispatch_to_schedtsk) .type Csym(dispatch_to_schedtsk), %functionCsym(dispatch_to_schedtsk): /* During interrupt disable PSR.EXL=0, IE=0, IM1=1 */ /* When 'tk_ext_tsk' and 'tk_exd_tsk' are called from invalid contexts, it may be called on IM1=0 state */ .set noat lui $at, %hi(TMP_STACK_TOP) addiu $sp, $at, %lo(TMP_STACK_TOP) // Set temporal stack .set at#if USE_DBGSPT lw $s0, Csym(ctxtsk) // s0 = ctxtsk#endif sw $zero, Csym(ctxtsk) // ctxtsk = NULL mfc0 $t8, $CP0_PSR // Dispatch disable/Interrupt enable and $t8, $t8, ~SR_IM(1) or $t8, $t8, SR_IE mtc0 $t8, $CP0_PSR // EXL=0, IE=1, IM1=0 j l_dispatch0_dispatch_entry: /* During interrupt disable PSR.EXL=0, IE=0, IM1=0 (Dispatch disable state) */ .set noat mfc0 $t8, $CP0_PSR xor $t8, $t8, SR_IE // Interrupt enable EXL=0, IE=1, IM1=0 mtc0 $t8, $CP0_PSR /* During interrupt enable PSR.EXL=0, IE=1, IM1=0 */ subu $sp, $sp, 28*8 // Context save mfhi $t8 mflo $t9 sd $t8, 0*8($sp) sd $t9, 1*8($sp) sd $at, 2*8($sp) sd $v0, 3*8($sp) sd $v1, 4*8($sp) sd $a0, 5*8($sp) sd $a1, 6*8($sp) sd $a2, 7*8($sp) sd $a3, 8*8($sp) sd $t0, 9*8($sp) sd $t1, 10*8($sp) sd $t2, 11*8($sp) sd $t3, 12*8($sp) sd $t4, 13*8($sp) sd $t5, 14*8($sp) sd $t6, 15*8($sp) sd $t7, 16*8($sp) sd $s0, 17*8($sp) sd $s1, 18*8($sp) sd $s2, 19*8($sp) sd $s3, 20*8($sp) sd $s4, 21*8($sp) sd $s5, 22*8($sp) sd $s6, 23*8($sp) sd $s7, 24*8($sp) sd $fp, 25*8($sp) sd $ra, 26*8($sp) sd $gp, 27*8($sp) .set at la $gp, _gp lw $s0, Csym(ctxtsk) // s0 = ctxtsk sd $sp, TCB_tskctxb+CTXB_ssp($s0) // Save 'ssp' to TCB sw $zero, Csym(ctxtsk) // ctxtsk = NULL l_dispatch0: /* During interrupt enable PSR.EXL=0, IE=1, IM1=0 */#if USE_DBGSPT lw $t0, hook_stop_jmp // Hook processing jr $t0 ret_hook_stop:#endif mfc0 $s7, $CP0_PSR // s7 = Interrupt enable EXL=0, IE=1, IM1=0 xor $s6, $s7, SR_IE // s6 = Interrupt disable EXL=0, IE=0, IM1=0 l_dispatch1: mtc0 $s6, $CP0_PSR // Interrupt disable NOP(HzD_MTC0 - HzS_INT) lw $s0, Csym(schedtsk) // s0 = schedtsk bnez $s0, l_dispatch2 // Is there 'schedtsk'? /* Because there is no task that should be executed, move to the power saving mode */ lw $t0, Csym(lowpow_discnt) // Is 'low_pow' disabled? bnez $t0, l_nolowpow subu $sp, $sp, 4*8 jal Csym(low_pow) // call low_pow() addu $sp, $sp, 4*8 l_nolowpow: mtc0 $s7, $CP0_PSR // Interrupt enable NOP(HzD_MTC0 - HzS_INT) j l_dispatch1 l_dispatch2: // Switch to 'schedtsk' /* During interrupt disable PSR.EXL=0, IE=0, IM1=0 */ sw $s0, Csym(ctxtsk) // ctxtsk = schedtsk ld $sp, TCB_tskctxb+CTXB_ssp($s0) // Restore 'ssp' from TCB lw $t1, TCB_isstack($s0) sw $t1, SSTKTOP // Switch system stack top /* Switch task eigenspace */ lw $t0, TCB_tskctxb+CTXB_lsid($s0) dmtc0 $t0, $CP0_EHI // Entry Hi.ASID = lsid#if TA_FPU /* Switch FPU context */ lw $t1, Csym(fpu_ctxtsk) beq $t1, $s0, l_same_fpuctx lb $t0, 248+7($sp) // PSR and $t0, $t0, ~(SR_CU1 >> 24) & 0xff sb $t0, 248+7($sp) // PSR.CU1 = 0 l_same_fpuctx:#endif#if USE_DBGSPT lw $t0, hook_exec_jmp // Hook processing jr $t0 ret_hook_exec:#endif lw $t8, TCB_reqdct($s0) // DCT request .set noat ld $t0, 0*8($sp) // Context restore ld $t1, 1*8($sp) mthi $t0 mtlo $t1 ld $at, 2*8($sp) ld $v0, 3*8($sp) ld $v1, 4*8($sp) ld $a0, 5*8($sp) ld $a1, 6*8($sp) ld $a2, 7*8($sp) ld $a3, 8*8($sp) ld $t0, 9*8($sp) ld $t1, 10*8($sp) ld $t2, 11*8($sp) ld $t3, 12*8($sp) ld $t4, 13*8($sp) ld $t5, 14*8($sp) ld $t6, 15*8($sp) ld $t7, 16*8($sp) ld $s0, 17*8($sp) ld $s1, 18*8($sp) ld $s2, 19*8($sp) ld $s3, 20*8($sp) ld $s4, 21*8($sp) ld $s5, 22*8($sp) ld $s6, 23*8($sp) ld $s7, 24*8($sp) ld $fp, 25*8($sp) ld $ra, 26*8($sp) ld $gp, 27*8($sp) addu $sp, $sp, 28*8 li $t9, 1 bne $t8, $t9, l_nodct_dispatch // Is there a DCT request? ld $t9, 3*8($sp) and $t9, $t9, TMF_CPL(3) // If the protected level is 0, DCT disable beqz $t9, l_nodct_dispatch mfc0 $t8, $CP0_PSR xor $t8, $t8, SR_IM(1) // Dispatch enable mtc0 $t8, $CP0_PSR j dct_startup // To DCT processing l_nodct_dispatch: /* The Interrupt and dispatch are enabled because PSR is resorted by returning from the handler.*/ MOVE_SSP_ISP dispatch EIT_RETURN dispatch .set at#if USE_DBGSPT/* * Task dispatcher hook routine call * void stop( ID tskid, INT lsid, UINT tskstat ) * void exec( ID tskid, INT lsid ) */ .extern Csym(hook_stopfn), 4 .extern Csym(hook_execfn), 4 .extern Csym(hook_dsp_gp), 4 .text .balign 4hook_stop: beqz $s0, l_notask // s0 = ctxtsk subu $sp, $sp, 5*8 sd $gp, 4*8($sp) lbu $a2, TCB_state($s0) // tskstat sll $a2, $a2, 1 lw $a1, TCB_tskctxb+CTXB_lsid($s0) // lsid lw $a0, TCB_tskid($s0) // tskid lw $t0, Csym(hook_stopfn) lw $gp, Csym(hook_dsp_gp) jalr $t0 // call stop(tskid, lsid, tskstat) ld $gp, 4*8($sp) addu $sp, $sp, 5*8 l_notask: j ret_hook_stophook_exec: subu $sp, $sp, 5*8 sd $gp, 4*8($sp) // s0 = ctxtsk lw $a1, TCB_tskctxb+CTXB_lsid($s0) // lsid lw $a0, TCB_tskid($s0) // tskid lw $t0, Csym(hook_execfn) lw $gp, Csym(hook_dsp_gp) jalr $t0 // call exec(tskid, lsid) ld $gp, 4*8($sp) addu $sp, $sp, 5*8 j ret_hook_exec/* * Set/Free task dispatcher hook routine */ .text .balign 4 .globl Csym(hook_dsp) .type Csym(hook_dsp), %functionCsym(hook_dsp): la $t0, hook_exec la $t1, hook_stop sw $t0, hook_exec_jmp sw $t1, hook_stop_jmp jr $ra .globl Csym(unhook_dsp) .type Csym(unhook_dsp), %functionCsym(unhook_dsp): la $t0, ret_hook_exec la $t1, ret_hook_stop sw $t0, hook_exec_jmp sw $t1, hook_stop_jmp jr $ra .sdata .balign 4 hook_exec_jmp: .int ret_hook_exec hook_stop_jmp: .int ret_hook_stop#endif /* USE_DBGSPT *//* ------------------------------------------------------------------------ *//* * Delayed interrupt handler * +---------------+ * isp -> | t8 | * +8 | t9 | * +16 | EPC | * +24 | PSR||taskmode | High:PSR Low:taskmode * +---------------+ * +32 | usp | Only RNG 1-3 * +---------------+ */ .text .balign 4 .globl Csym(delayed_interrupt) .type Csym(delayed_interrupt), %functionCsym(delayed_interrupt): .set noat /* Interrupt disable PSR.EXL=1, IE=1, IM1=0 (IM1,IM0 is disabled by exception entry processing) */ lui $t8, %hi(Csym(int_stack_top)) lw $t8, %lo(Csym(int_stack_top))($t8) lw $t9, ISTKPOS // t9 = isp subu $t8, $t8, 5*8 sltu $t8, $t9, $t8 // Dispatch disable if it is a nesting interrupt bnez $t8, l_nodispatch1 mfc0 $t8, $CP0_OCC xor $t8, OC_IP(1) // Clear delayed interrupt request IP1 = 0 mtc0 $t8, $CP0_OCC lui $t8, %hi(Csym(ctxtsk)) // If ctxtsk == schedtsk, lui $t9, %hi(Csym(schedtsk)) // dispatch not required. lw $t8, %lo(Csym(ctxtsk))($t8) lw $t9, %lo(Csym(schedtsk))($t9) beq $t8, $t9, l_nodispatch2 mfc0 $t8, $CP0_PSR xor $t8, $t8, SR_IM(0)|SR_EXL|SR_IE // EXL=0, IE=0, IM1=0, IM0=1 mtc0 $t8, $CP0_PSR MOVE_ISP_SSP delayed_interrupt j _dispatch_entry // To dispatch processing l_nodispatch1: lw $t8, 3*8+4($t9) // PSR xor $t8, $t8, SR_IM(1) // By returning from a delayed interrupt, sw $t8, 3*8+4($t9) // Disable IP1 so that a delayed interrupt will not occur again l_nodispatch2: EIT_RETURN delayed_interrupt .set at/* ------------------------------------------------------------------------ */#if TA_FPU/* * Coprocessor disable exception * FPU context switch * +---------------+ * isp -> | t8 | * +8 | t9 | * +16 | EPC | * +24 | PSR||taskmode | High:PSR Low:taskmode * +---------------+ * +32 | usp | Only RNG 1-3 * +---------------+ * t8 = Vector table address */ .text .balign 4 .globl Csym(unavailable_cop) .type Csym(unavailable_cop), %functionCsym(unavailable_cop): .set noat /* Interrupt disable PSR.EXL=1, IE=? */ mfc0 $kt0, $CP0_OCC // Exceptions, except for CP1(FPU), are srl $kt0, $kt0, 28 // Invalid use of coprocessor and $kt0, $kt0, OC_CE >> 28 subu $kt0, $kt0, 1 bnez $kt0, l_goto_defaulthdr1 mfc0 $t9, $CP0_PSR // t9 = PSR li $kt0, ~(SR_EXL|SR_IE) and $kt0, $t9, $kt0 // EXL=0, IE=0 mtc0 $kt0, $CP0_PSR subu $sp, $sp, 3*8 // Save register for work sd $t0, 0*8($sp) sd $t1, 1*8($sp) sd $gp, 2*8($sp) la $gp, _gp lw $t0, Csym(ctxtsk) // t0 = ctxtsk beqz $t0, l_goto_defaulthdr2 // If ctxtsk == NULL, invalid use of FPU. lw $t1, TCB_tskatr($t0) // If TA_FPU attribute is not specified, and $t1, $t1, TA_FPU // invalid use of FPU. beqz $t1, l_goto_defaulthdr2 mfc0 $t9, $CP0_PSR li $t8, SR_CU1|SR_FR or $t9, $t9, $t8 mtc0 $t9, $CP0_PSR // FPU enable CU1=1, FR=1 lw $t9, Csym(fpu_ctxtsk) // t9 = fpu_ctxtsk beq $t9, $t0, l_nosw_fpu // If fpu_ctxtsk == ctxtsk, // do not need to switch FPU context. beqz $t9, l_nosave_fpu // If fpu_ctxtsk == NULL, // do not need to save FPU context. lw $t1, TCB_isstack($t9) // Save FPU context sdc1 $f0, 0*8($t1) sdc1 $f1, 1*8($t1) sdc1 $f2, 2*8($t1) sdc1 $f3, 3*8($t1) sdc1 $f4, 4*8($t1) sdc1 $f5, 5*8($t1) sdc1 $f6, 6*8($t1) sdc1 $f7, 7*8($t1) sdc1 $f8, 8*8($t1) sdc1 $f9, 9*8($t1) sdc1 $f10, 10*8($t1) sdc1 $f11, 11*8($t1) sdc1 $f12, 12*8($t1) sdc1 $f13, 13*8($t1) sdc1 $f14, 14*8($t1) sdc1 $f15, 15*8($t1) sdc1 $f16, 16*8($t1) sdc1 $f17, 17*8($t1) sdc1 $f18, 18*8($t1) sdc1 $f19, 19*8($t1) sdc1 $f20, 20*8($t1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -