📄 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 (M32104) * 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"/* ------------------------------------------------------------------------ *//* * Dispatcher * dispatch_to_schedtsk: * Throw away the current contexts and forcibly dispatch to * 'schedtsk.' * Called directly by jump (jmp) and do not return. * Called on the undefined stack state (undefined 'sp'). * Called on the interrupt disabled state. * dispatch_entry: * Normal dispatch processing. Called by 'trap #4.' * _ret_int_dispatch: * Called when dispatch is required by 'ret_int().' * * In either case, the stack mode is called by SPU (SM=1). * * Contexts to save * Save registers except for SSP to a stack. Save SSP to TCB. * * High Address +---------------+ * | R7 | * | R6 | * | BPC | Saved by interrupt entry * | PSW | routines until here. * +---------------+ * | R8-14 | * | R0-5 | * Saved to TCB SP => | ACC | * Low Address +---------------+ * */ /* Temporal stack used when 'dispatch_to_schedtsk' is called */#define TMP_STACK_SZ (4*1024)#define TMP_STACK_TOP (tmp_stack + TMP_STACK_SZ) .lcomm tmp_stack, TMP_STACK_SZ .text .balign 4 .globl Csym(dispatch_to_schedtsk) .globl Csym(dispatch_entry)Csym(dispatch_to_schedtsk): /* During interrupt disable PSW.IE=0, SM=1 */ seth r0, #shigh(TMP_STACK_TOP) // Set temporal stack add3 sp, r0, #low(TMP_STACK_TOP) ldi r1, #1 // Dispatch disable seth r0, #CsymH(dispatch_disabled) st r1, @(CsymL(dispatch_disabled), r0) seth r10, #CsymH(ctxtsk) // R10 = &ctxtsk add3 r10, r10, #CsymL(ctxtsk) ldi r0, #0#if USE_DBGSPT ld r8, @r10#endif st r0, @r10 // ctxtsk = NULL ldi r0, #PSW_IE | PSW_SM // Interrupt enable mvtc r0, psw bra l_dispatch0Csym(dispatch_entry): ld r7, @sp or3 r7, r7, #PSW_BIE st r7, @sp_ret_int_dispatch: /* During interrupt disable PSW.IE=0, SM=1 */ ldi r7, #1 // Dispatch disable seth r6, #CsymH(dispatch_disabled) st r7, @(CsymL(dispatch_disabled), r6) ldi r7, #PSW_IE | PSW_SM // Interrupt enable mvtc r7, psw /* During interrupt enable PSW.IE=1, SM=1 */ st r14, @-sp // Context save st r13, @-sp st r12, @-sp st r11, @-sp st r10, @-sp st r9, @-sp st r8, @-sp st r5, @-sp st r4, @-sp st r3, @-sp st r2, @-sp st r1, @-sp st r0, @-sp mvfaclo r1 mvfachi r0 st r1, @-sp st r0, @-sp seth r10, #CsymH(ctxtsk) // R10 = &ctxtsk add3 r10, r10, #CsymL(ctxtsk) ld r8, @r10 st sp, @(TCB_tskctxb+CTXB_ssp, r8) // Save SSP to TCB l_dispatch0: /* During interrupt enable PSW.IE=1, SM=1 */#if USE_DBGSPT seth r0, #shigh(hook_stop_jmp) // Hook processing ld r0, @(low(hook_stop_jmp), r0) jmp r0 ret_hook_stop:#endif ldi r0, #0 st r0, @r10 // ctxtsk = NULL seth r11, #CsymH(schedtsk) // R11 = &schedtsk seth r12, #CsymH(lowpow_discnt) // R12 = &lowpow_discnt l_dispatch1: ldi r0, #PSW_SM // Interrupt disable mvtc r0, psw ld r8, @(CsymL(schedtsk), r11) // R8 = schedtsk bnez r8, l_dispatch2 // Is there 'schedtsk'? /* Because there is no task that should be executed, move to the power-saving mode */ ld r0, @(CsymL(lowpow_discnt), r12) // Is 'low_pow' disabled? bnez r0, l_dispatch11 bl Csym(low_pow) // call low_pow() l_dispatch11: ldi r0, #PSW_IE | PSW_SM // Interrupt enable mvtc r0, psw bra l_dispatch1 l_dispatch2: // Switch to 'schedtsk' /* During interrupt disable PSW.IE=0, SM=1 */ st r8, @r10 // ctxtsk = schedtsk ld sp, @(TCB_tskctxb+CTXB_ssp, r8) // Restore SSP from TCB#if USE_DBGSPT seth r0, #shigh(hook_exec_jmp) // Hook processing ld r0, @(low(hook_exec_jmp), r0) jmp r0 ret_hook_exec:#endif ldi r7, #0 // Dispatch enable seth r6, #CsymH(dispatch_disabled) st r7, @(CsymL(dispatch_disabled), r6) ld r6, @(TCB_reqdct, r8) // DCT request ld r0, @sp+ // Context restore ld r1, @sp+ mvtachi r0 mvtaclo r1 ld r0, @sp+ ld r1, @sp+ ld r2, @sp+ ld r3, @sp+ ld r4, @sp+ ld r5, @sp+ ld r8, @sp+ ld r9, @sp+ ld r10, @sp+ ld r11, @sp+ ld r12, @sp+ ld r13, @sp+ ld r14, @sp+ seth r7, #high(0x80000000) beq r6, r7, Csym(dct_startup) // To DTC processing EXC_RETURN dispatch#if USE_DBGSPT/* * Task dispatcher hook routine call * void stop( ID tskid, INT lsid, UINT tskstat ) * void exec( ID tskid, INT lsid ) */ .text .balign 4hook_stop: beqz r8, l_notask // r8 = ctxtsk ldi r0, #PSW_IE | PSW_SM // PSW setting value for hook call mvfc r9, psw // PSW save mvtc r0, psw /* During interrupt enable PSW.IE=1, SM=1 */ seth r7, #CsymH(hook_stopfn) ld r7, @(CsymL(hook_stopfn), r7) ldb r2, @(TCB_state, r8) slli r2, #1 // tskstat ld r1, @(TCB_tskctxb + CTXB_lsid, r8) // lsid ld r0, @(TCB_tskid, r8) // tskid jl r7 // call stop(tskid, lsid, tskstat) mvtc r9, psw // PSW restore l_notask: bra ret_hook_stophook_exec: ldi r0, #PSW_IE | PSW_SM // PSW setting value for hook call mvfc r9, psw // PSW save mvtc r0, psw /* During interrupt enable PSW.IE=1, SM=1 */ seth r7, #CsymH(hook_execfn) ld r7, @(CsymL(hook_execfn), r7) // r8 = ctxtsk ld r1, @(TCB_tskctxb + CTXB_lsid, r8) // lsid ld r0, @(TCB_tskid, r8) // tskid jl r7 // call exec(tskid, lsid) mvtc r9, psw // PSW restore bra ret_hook_exec/* * Set/Clear task dispatcher hook routine */ .text .balign 4 .globl Csym(hook_dsp)Csym(hook_dsp): seth r2, #shigh(hook_exec) seth r3, #shigh(hook_stop) add3 r2, r2, #low(hook_exec) add3 r3, r3, #low(hook_stop) seth r0, #shigh(hook_exec_jmp) seth r1, #shigh(hook_stop_jmp) st r2, @(low(hook_exec_jmp), r0) st r3, @(low(hook_stop_jmp), r1) jmp lr .globl Csym(unhook_dsp)Csym(unhook_dsp): seth r2, #shigh(ret_hook_exec) seth r3, #shigh(ret_hook_stop) add3 r2, r2, #low(ret_hook_exec) add3 r3, r3, #low(ret_hook_stop) seth r0, #shigh(hook_exec_jmp) seth r1, #shigh(hook_stop_jmp) st r2, @(low(hook_exec_jmp), r0) st r3, @(low(hook_stop_jmp), r1) jmp lr .data .balign 4 hook_exec_jmp: .long ret_hook_exec hook_stop_jmp: .long ret_hook_stop#endif /* USE_DBGSPT *//* ------------------------------------------------------------------------ *//* * High level programming language routine for interrupt handler * Called by interrupt entry routine on the state saved in the * stack as shown below. * Depending on the types of EIT that occurred, the stack mode is * different. * High Address +---------------+ * | R7 | * | R6 | * | BPC | * SP => | PSW|ICU1_ISTS | * Low Address +---------------+ * * Also, the 'vector table address' is saved in R7. * Vector number = (R7 - EIT_VECTBL) / 4 */ .text .balign 4 .globl Csym(defaulthdr_startup) .globl Csym(inthdr_startup)Csym(defaulthdr_startup): /* During interrupt disable PSW.IE=0 SM=? */ st r13, @-sp // R13 save add3 r13, sp, #4 // Save 'sp' position on handler entry ldi r6, #0 // Stack mode switch mvtc r6, psw // PSW.IE=0, SM=0 ld24 r6, #EIT_VECTBL sub r7, r6 ldi r6, #0 // R6 = Default handler index srai r7, #2 // R7 = Vector number bra l_inthdr1Csym(inthdr_startup): /* During interrupt disable PSW.IE=0 SM=? */ st r13, @-sp // R13 save add3 r13, sp, #4 // Save 'sp' position on handler entry ldi r6, #0 // Stack mode switch mvtc r6, psw // PSW.IE=0, SM=0 ld24 r6, #EIT_VECTBL sub r7, r6 mv r6, r7 // R6 = Interrupt handler index srai r7, #2 // R7 = Vector number l_inthdr1: /* During interrupt disable PSW.IE=0, SM=0 */ st lr, @-sp // Register save st r5, @-sp st r4, @-sp st r3, @-sp st r2, @-sp st r1, @-sp st r0, @-sp mvfaclo r1 mvfachi r0 st r1, @-sp st r0, @-sp#if USE_DBGSPT seth r5, #shigh(hook_ienter_jmp) // Hook processing ld r5, @(low(hook_ienter_jmp), r5) jmp r5 ret_hook_ienter:#endif seth r5, #CsymH(hll_inthdr) add r5, r6 ld r5, @(CsymL(hll_inthdr), r5) mv r1, r13 // sp mv r0, r7 // dintno jl r5 // call hll_inthdr[n](dintno, sp)#if USE_DBGSPT seth r5, #shigh(hook_ileave_jmp) // Hook processing ld r5, @(low(hook_ileave_jmp), r5) jmp r5 ret_hook_ileave:#endif /* Unknown interrupt disable state PSW.IE=? SM=0 */ ld r0, @sp+ // Register restore ld r1, @sp+ mvtachi r0 mvtaclo r1 ld r0, @sp+ ld r1, @sp+ ld r2, @sp+ ld r3, @sp+ ld r4, @sp+ ld r5, @sp+ ld lr, @sp+ ld r13, @r13 // Return stack mode mvtc r13, psw ld r13, @sp+ // R13 restore trap #TRAP_RETINT // tk_ret_int()#if USE_DBGSPT/* * Interrupt handler hook routine call */ .text .balign 4hook_ienter: seth r5, #CsymH(hook_ienterfn) ld r5, @(CsymL(hook_ienterfn), r5) st r7, @-sp // R7 vector number save st r6, @-sp // R6 handler index save mv r1, r13 // sp mv r0, r7 // dintno jl r5 // call enter(dintno, sp) ld r6, @sp+ // R6,R7 restore ld r7, @sp // Leave vector number on stack bra ret_hook_ienterhook_ileave: seth r5, #CsymH(hook_ileavefn) ld r5, @(CsymL(hook_ileavefn), r5) mv r1, r13 // sp ld r0, @sp+ // dintno (Restore vector number from stack) jl r5 // call leave(dintno, sp) bra ret_hook_ileave/* * Set/Clear interrupt handler hook routine */ .text .balign 4 .globl Csym(hook_int)Csym(hook_int): seth r2, #shigh(hook_ienter) seth r3, #shigh(hook_ileave) add3 r2, r2, #low(hook_ienter) add3 r3, r3, #low(hook_ileave) seth r0, #shigh(hook_ienter_jmp) seth r1, #shigh(hook_ileave_jmp) st r2, @(low(hook_ienter_jmp), r0) st r3, @(low(hook_ileave_jmp), r1) jmp lr .globl Csym(unhook_int)Csym(unhook_int): seth r2, #shigh(ret_hook_ienter) seth r3, #shigh(ret_hook_ileave) add3 r2, r2, #low(ret_hook_ienter) add3 r3, r3, #low(ret_hook_ileave) seth r0, #shigh(hook_ienter_jmp) seth r1, #shigh(hook_ileave_jmp) st r2, @(low(hook_ienter_jmp), r0) st r3, @(low(hook_ileave_jmp), r1) jmp lr .data .balign 4 hook_ienter_jmp: .long ret_hook_ienter hook_ileave_jmp: .long ret_hook_ileave#endif /* USE_DBGSPT *//* * tk_ret_int() processing * When called, the interrupt stack is configured as shown below. * Depending on the types of EIT that occurred, the stack mode is * different. * High Address +---------------+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -