📄 cpu_support.s
字号:
addu $sp, $sp, 4*8 j l_retsvc l_illegal_svc: li $v0, E_RSFN j l_retsvc l_oacv_err: li $v0, E_OACV j l_retsvc#if USE_DBGSPT/* * System call/Extended SVC hook routine call * VP enter( FN fncd, TD_CALINF *calinf, ... ) * void leave( FN fncd, INT ret, VP exinf ) * * typedef struct td_calinf { * DW ssp; System stack pointer * DW ra; Return address when calling * DW fp; Flame pointer when calling * } TD_CALINF; */ .extern Csym(hook_enterfn), 4 .extern Csym(hook_leavefn), 4 .extern Csym(hook_svc_gp), 4 .text .balign 4hook_enter: subu $sp, $sp, 9*8 sd $a0, 3*8($sp) // Save argument sd $a1, 4*8($sp) sd $a2, 5*8($sp) sd $a3, 6*8($sp) sd $s1, 7*8($sp) // Save register for work sd $t8, 8*8($sp) move $s1, $sp // s1 = &TD_CALINF addu $t0, $fp, 2*8 // Create TD_CALINF sd $t0, 0*8($sp) // ssp sd $ra, 1*8($sp) // ra ld $t0, 0*8($fp) sd $t0, 2*8($sp) // fp bgez $s0, l_enter_p1 // s0 = Function code // <0: System call // >=0: Extended SVC lw $t1, 3*8($fp) // taskmode srl $t3, $s0, 8 and $t3, $t3, 0xff // t3 = Number of arguments and $t1, $t1, TMF_PPL(3) // t1 = Protected level when calling addu $t4, $fp, 4*8 // t4 = ssp Argument stack position (RNG0) beqz $t1, l_enter1 ld $t4, 4*8($fp) // t4 = usp Argument stack position (RNG1-3) l_enter1: bltu $t3, 5, l_enter_p4 ld $t0, 4*8($t4) subu $sp, $sp, 1*8 sd $t0, ($sp) // Fifth argument l_enter_p4: bltu $t3, 4, l_enter_p3 subu $sp, $sp, 1*8 sd $a3, ($sp) // Fourth argument l_enter_p3: bltu $t3, 3, l_enter_p2 subu $sp, $sp, 1*8 sd $a2, ($sp) // Third argument l_enter_p2: move $a3, $a1 // Second argument l_enter_p1: move $a2, $a0 // First argument move $a1, $s1 // calinf move $a0, $s0 // fncd subu $sp, $sp, 4*8 lw $t0, Csym(hook_enterfn) lw $gp, Csym(hook_svc_gp) jalr $t0 // exinf = enter(fncd, ...) la $gp, _gp move $sp, $s1 // Return stack position ld $a0, 3*8($sp) // Restore argument ld $a1, 4*8($sp) ld $a2, 5*8($sp) ld $a3, 6*8($sp) ld $s1, 7*8($sp) // Restore register for work ld $t8, 8*8($sp) sd $v0, 8*8($sp) // 'exinf' save addu $sp, $sp, 8*8 // Save and leave 'exinf' j ret_hook_enterhook_leave: li $a2, 0 // exinf = 0 subu $t0, $fp, $sp // Whether 'hook_enter' is executed beq $t0, 2*8, l_leave1 // Check by stack usage // 'hook_enter' is called ld $a2, ($sp) // exinf addu $sp, $sp, 1*8 l_leave1: move $a1, $v0 // ret move $a0, $s0 // fncd move $s0, $v0 // s0 = Return value 'ret' save lw $t0, Csym(hook_leavefn) lw $gp, Csym(hook_svc_gp) subu $sp, $sp, 4*8 jalr $t0 // call leave(fncd, ret, exinf) addu $sp, $sp, 4*8 la $gp, _gp move $v0, $s0 // v0 = Return value 'ret' restore j ret_hook_leave/* * Set/Free system call/extended SVC hook routine */ .text .balign 4 .globl Csym(hook_svc) .type Csym(hook_svc), %functionCsym(hook_svc): la $t0, hook_enter la $t1, hook_leave sw $t0, hook_enter_jmp sw $t1, hook_leave_jmp jr $ra .globl Csym(unhook_svc) .type Csym(unhook_svc), %functionCsym(unhook_svc): la $t0, ret_hook_enter la $t1, ret_hook_leave sw $t0, hook_enter_jmp sw $t1, hook_leave_jmp jr $ra .sdata .balign 4 hook_enter_jmp: .int ret_hook_enter hook_leave_jmp: .int ret_hook_leave#endif /* USE_DBGSPT *//* ------------------------------------------------------------------------ */#if USE_DBGSPT/* * Debugger support function service call entry table */ .text .balign 4 .type _tdsvctbl, %object_tdsvctbl: .int Csym(no_support)#include <sys/svc/tdsvctbl.h>/* * Debugger support function service call entry * +---------------+ * isp/ssp -> | t8 | (Overwrite and save 'gp') * +8 | t9 | (Overwrite and save 'ra') * +16 | EPC | * +24 | PSR||taskmode | High:PSR Low:taskmode * +---------------+ * +32 | usp | Only RNG 1-3 * +---------------+ */ .text .balign 4 .globl Csym(call_dbgspt) .type Csym(call_dbgspt), %functionCsym(call_dbgspt): /* During interrupt disable PSR.EXL=1, IE=? */ mfc0 $t0, $CP0_PSR and $t1, $t0, ~(SR_EXL|SR_IE) mtc0 $t1, $CP0_PSR // EXL=0, IE=0 Interrupt disable MOVE_ISP_SSP call_dbgspt and $t1, $t0, ~SR_EXL mtc0 $t1, $CP0_PSR // EXL=0, IE=? caller's state sd $gp, 0*8($sp) // gp save (overwrite 't8') sd $ra, 1*8($sp) // ra save (overwrite 't9') move $t8, $gp // t8 = Caller gp la $gp, _gp lw $t1, 3*8($sp) // 'taskmode' when calling lw $t0, Csym(svc_call_limit) // Call protected level limit and $t1, $t1, TMF_CPL(3) // t1 = Protected level when calling bgt $t1, $t0, b_oacv_err sra $t2, $v0, 16 // t2 = Function number bgt $t2, N_TDFN - 0x8000, b_illegal_svc sll $t2, $t2, 2 lw $t0, _tdsvctbl - (-0x8000 << 2)($t2) subu $sp, $sp, 6*8 // Always set number of arguments to 6 sd $t8, 5*8($sp) // Sixth argument = Caller gp jalr $t0 // T-Kernel/DS service call addu $sp, $sp, 6*8 b_retsvc: ld $gp, 0*8($sp) // Restore register for work ld $ra, 1*8($sp) MOVE_SSP_ISP call_dbgspt CALL_RETURN call_dbgspt b_illegal_svc: li $v0, E_RSFN j b_retsvc b_oacv_err: li $v0, E_OACV j b_retsvc#endif /* USE_DBGSPT *//* ------------------------------------------------------------------------ *//* * High level programming language routine for timer handler */ .text .balign 4 .globl Csym(timer_handler_startup) .type Csym(timer_handler_startup), %functionCsym(timer_handler_startup): /* During interrupt disable PSR.EXL=1 IE=1 */ .set noat mfc0 $kt0, $CP0_PSR li $kt1, SR_DS|SR_IMMSK and $kt0, $kt0, $kt1 li $kt1, SR_XX|SR_FR|SR_KX|SR_SX|SR_UX or $kt0, $kt0, $kt1 mtc0 $kt0, $CP0_PSR // PSR setting EXL=0, IE=0 interrupt disable subu $sp, $sp, 24*8 // Register save sd $at, 4*8($sp) sd $v0, 5*8($sp) sd $v1, 6*8($sp) sd $a0, 7*8($sp) sd $a1, 8*8($sp) sd $a2, 9*8($sp) sd $a3, 10*8($sp) sd $t0, 11*8($sp) sd $t1, 12*8($sp) sd $t2, 13*8($sp) sd $t3, 14*8($sp) sd $t4, 15*8($sp) sd $t5, 16*8($sp) sd $t6, 17*8($sp) sd $t7, 18*8($sp) sd $gp, 19*8($sp) sd $fp, 20*8($sp) sd $ra, 21*8($sp) mfhi $t0 mflo $t1 sd $t0, 22*8($sp) sd $t1, 23*8($sp) .set at la $gp, _gp jal Csym(timer_handler) // call timer_handler() /* Return by interrupt enable */ .set noat ld $at, 4*8($sp) // Register restore ld $v0, 5*8($sp) ld $v1, 6*8($sp) ld $a0, 7*8($sp) ld $a1, 8*8($sp) ld $a2, 9*8($sp) ld $a3, 10*8($sp) ld $t0, 11*8($sp) ld $t1, 12*8($sp) ld $t2, 13*8($sp) ld $t3, 14*8($sp) ld $t4, 15*8($sp) ld $t5, 16*8($sp) ld $t6, 17*8($sp) ld $t7, 18*8($sp) ld $gp, 19*8($sp) ld $fp, 20*8($sp) ld $ra, 21*8($sp) ld $t8, 22*8($sp) ld $t9, 23*8($sp) mthi $t8 mtlo $t9 addu $sp, $sp, 24*8 EIT_RETURN timer_handler_startup .set at/* ------------------------------------------------------------------------ *//* * Delayed context trap (DCT) * Task exception handler startup * When called, the system stack is configured as shown below. * +---------------+ * ssp -> | t8 | * +8 | t9 | * +16 | EPC | * +24 | PSR||taskmode | High:PSR Low:taskmode * +32 | usp | * +---------------+ */ .text .balign 4dct_startup: /* During Interrupt disable */ .set noat subu $sp, $sp, 23*8 // Register save mfhi $t8 mflo $t9 sd $t8, 4*8($sp) sd $t9, 5*8($sp) sd $at, 6*8($sp) sd $v0, 7*8($sp) sd $v1, 8*8($sp) sd $a0, 9*8($sp) sd $a1, 10*8($sp) sd $a2, 11*8($sp) sd $a3, 12*8($sp) sd $t0, 13*8($sp) sd $t1, 14*8($sp) sd $t2, 15*8($sp) sd $t3, 16*8($sp) sd $t4, 17*8($sp) sd $t5, 18*8($sp) sd $t6, 19*8($sp) sd $t7, 20*8($sp) sd $ra, 21*8($sp) sd $gp, 22*8($sp) .set at la $gp, _gp addu $a0, $sp, 23*8 jal Csym(setup_texhdr) // call setup_texhdr(ssp) /* Return in interrupt enable state */ .set noat ld $t8, 4*8($sp) // Register restore ld $t9, 5*8($sp) mthi $t8 mtlo $t9 ld $at, 6*8($sp) ld $v0, 7*8($sp) ld $v1, 8*8($sp) ld $a0, 9*8($sp) ld $a1, 10*8($sp) ld $a2, 11*8($sp) ld $a3, 12*8($sp) ld $t0, 13*8($sp) ld $t1, 14*8($sp) ld $t2, 15*8($sp) ld $t3, 16*8($sp) ld $t4, 17*8($sp) ld $t5, 18*8($sp) ld $t6, 19*8($sp) ld $t7, 20*8($sp) ld $ra, 21*8($sp) ld $gp, 22*8($sp) addu $sp, $sp, 23*8 MOVE_SSP_ISP dct_startup EIT_RETURN dct_startup .set at/* * Return from task exception handler * +---------------+ * usp -> | PC | Return address from task exception handler * +---------------+ * * +---------------+ * ssp/isp -> | t8 | * +8 | t9 | * +16 | EPC | * +24 | PSR||taskmode | High:PSR Low:taskmode * +32 | usp | * +---------------+ * * If the call is invalid, call the default handler. */ .text .balign 4 .globl Csym(rettex_entry) .type Csym(rettex_entry), %functionCsym(rettex_entry): /* Interrupt disable PSR.EXL=1, IE=1 */ .set noat mfc0 $t9, $CP0_PSR and $kt0, $t9, SR_IE // A call from interrupt disable state is invalid beqz $kt0, l_illegal_rettex lw $kt1, ISTKPOS lw $kt0, 3*8($kt1) // taskmode and $kt0, $kt0, TMF_CPL(3) // A call from protected level 0 is invalid. beqz $kt0, l_illegal_rettex xor $kt0, $t9, SR_EXL mtc0 $kt0, $CP0_PSR // EXL=0, IE=1 Interrupt enable /* To access the user stack, it must not be the task independent part */ MOVE_ISP_SSP rettex_entry ld $t9, 4*8($sp) // usp ld $t8, ($t9) // PC sd $t8, 2*8($sp) // EPC = PC addu $t9, $t9, 1*8 // usp++ sd $t9, 4*8($sp) // Delete PC from stack MOVE_SSP_ISP rettex_entry CALL_RETURN rettex_entry l_illegal_rettex: lw $kt0, EITVEC(EIT_DEFAULT) jr $kt0 .set at/* ------------------------------------------------------------------------ *//* * User defined handler call * INT CallUserHandler( INT p1, INT p2, INT p3, FP hdr, VP gp ) */ .text .balign 4 .globl Csym(CallUserHandler) .type Csym(CallUserHandler), %functionCsym(CallUserHandler): subu $sp, $sp, 6*8 sd $gp, 4*8($sp) sd $ra, 5*8($sp) lw $gp, (6+4)*8($sp) jalr $a3 ld $gp, 4*8($sp) ld $ra, 5*8($sp) addu $sp, $sp, 6*8 jr $ra/* ------------------------------------------------------------------------ *//* * Device driver call * INT _CallDeviceDriver( INT p1, INT p2, INT p3, INT p4, FP drv, VP gp ) */ .text .balign 4 .globl Csym(_CallDeviceDriver) .type Csym(_CallDeviceDriver), %functionCsym(_CallDeviceDriver): subu $sp, $sp, 6*8 sd $gp, 4*8($sp) sd $ra, 5*8($sp) lw $t9, (6+4)*8($sp) lw $gp, (6+5)*8($sp) jalr $t9 ld $gp, 4*8($sp) ld $ra, 5*8($sp) addu $sp, $sp, 6*8 jr $ra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -