📄 cpu_asm.s
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * cpu_asm.S (memory) * * SH7727-dependent functions */#define _in_asm_source_#include <machine.h>#include <tk/asm.h>#include <sys/sysinfo.h>#include <sys/memdef.h>#include "cpu_asm.h"/* * Call system program * ER CallSysProgInit( INT ac, UB *av[], FP entry ) */ .text .balign 2 .globl Csym(CallSysProgInit) .type Csym(CallSysProgInit), @functionCsym(CallSysProgInit): mov.l r8, @-SP // Save register mov.l r9, @-SP mov.l r10, @-SP mov.l r11, @-SP mov.l r12, @-SP mov.l r13, @-SP mov.l r14, @-SP sts.l pr, @-SP jsr @r6 // call entry(ac, av) nop lds.l @SP+, pr // Restore register mov.l @SP+, r14 mov.l @SP+, r13 mov.l @SP+, r12 mov.l @SP+, r11 mov.l @SP+, r10 mov.l @SP+, r9 rts mov.l @SP+, r8/* ------------------------------------------------------------------------ *//* * Dedicated stack for page fault handler * Used as virtual memory within page fault handler * System stack cannot be used. */#define PAGEFAULTHDR_STACKSZ (3 * 1024)#define PAGEFAULTHDR_STACKTOP (pagefaulthdr_stack + PAGEFAULTHDR_STACKSZ) .lcomm pagefaulthdr_stack, PAGEFAULTHDR_STACKSZ/* * Page fault handler entry * TA_ASM-format handler */ .text .balign 2 .globl Csym(asmPageFaultHdr) .type Csym(asmPageFaultHdr), @functionCsym(asmPageFaultHdr): /* SR.BL=1, SR.RB=1, SR.I=15 */ mov.l r0, @-ISP // R0_BANK1 (Vector index + factor) Save mov.l r4, @-ISP // R4_BANK1 Save mov.l SP, @-ISP // For page fault handler only mov.l P_STACKTOP, r0 // Use stack. mov.l P_STACKLIMIT, r4 cmp/hi r4, SP bf l_chgstk cmp/hs SP, r0 bt l_nochgstk l_chgstk: mov r0, SP l_nochgstk: stc.l r4_bank, @-SP // Save register stc.l r5_bank, @-SP stc.l r6_bank, @-SP mov.l P_EXPEVT, r7 // Obtain exception information. mov.l P_TEA, r0 mov.l @r7, r4 // Save EXPEVT in r4_bank1. mov.l P_MMUCR, r7 ldc r4, r4_bank // r4_bank0 = EXPEVT ldc.l @r0+, r5_bank // r5_bank0 = TEA ldc.l @r7+, r6_bank // r6_bank0 = MMUCR mov.l P_SR_NOBLOCK, r7 // Reset exception block. ldc r7, sr // Switch register banks. /* SR.BL=0, SR.RB=0, SR.I=15 */ mov.l r0, @-SP // Save register mov.l r1, @-SP mov.l r2, @-SP mov.l r3, @-SP mov.l r7, @-SP sts.l mach, @-SP sts.l macl, @-SP sts.l pr, @-SP mov.l P_HDRENT, r0 jsr @r0 // call PageFaultHdr(EXPEVT,TEA,MMUCR) nop ldc r0, r0_bank // Save return value in r0_bank1. lds.l @SP+, pr // Restore register lds.l @SP+, macl lds.l @SP+, mach mov.l @SP+, r7 mov.l @SP+, r3 mov.l @SP+, r2 mov.l @SP+, r1 mov.l @SP+, r0 mov.l @SP+, r6 mov.l @SP+, r5 mov.l P_SR_NOBL_RB, r4 // Switch register banks. ldc r4, sr /* SR.BL=0, SR.RB=1, SR.I=15 */ ldc.l @SP+, r4_bank // R4_BANK0 Restore mov.l @ISP+, SP // Turn back stack tst r0, r0 bf l_enter_bms mov.l @ISP+, r4 // R4_BANK1 Restore mov.l @ISP+, r0 // R0_BANK1 Restore trapa #TRAP_RETINT // ret_int() l_enter_bms: mov.l P_SR_BLOCK, r0 // Exception block ldc r0, sr /* SR.BL=1, SR.RB=1, SR.I=15 */ mov.l P_DEFHDR, r7 mov.l P_EXPEVT, r0 mov.l @r7, r7 mov.l r4, @r0 // Restore exception code in EXPEVT. mov.l @ISP+, r4 // R4_BANK1 Restore jmp @r7 // To BMS default handler. mov.l @ISP+, r0 // R0_BANK1 Restore/* * Provisional page fault handler entry * Used provisionally until T-Kernel starts. * Switched to a regular page fault handler after T-Kernel startup. */ .text .balign 2 .globl Csym(asmTmpPageFaultHdr) .type Csym(asmTmpPageFaultHdr), @functionCsym(asmTmpPageFaultHdr): /* SR.BL=1, SR.RB=1, SR.I=15 */ stc.l r4_bank, @-ISP // Save register stc.l r5_bank, @-ISP stc.l r6_bank, @-ISP mov.l SP, @-ISP // For page fault handler only mov.l P_STACKTOP, SP // Use stack. mov.l P_EXPEVT, r7 // Obtain exception information. mov.l P_TEA, r0 ldc.l @r7+, r4_bank // r4_bank0 = EXPEVT mov.l P_MMUCR, r7 ldc.l @r0+, r5_bank // r5_bank0 = TEA ldc.l @r7+, r6_bank // r6_bank0 = MMUCR mov.l P_SR_NOBLOCK, r7 // Reset exception block. ldc r7, sr // Switch register banks. /* SR.BL=0, SR.RB=0, SR.I=15 */ mov.l r0, @-SP // Restore register mov.l r1, @-SP mov.l r2, @-SP mov.l r3, @-SP mov.l r7, @-SP sts.l mach, @-SP sts.l macl, @-SP sts.l pr, @-SP mov.l P_TMPHDR, r0 jsr @r0 // call TmpPageFaultHdr(EXPEVT,TEA,MMUCR) nop lds.l @SP+, pr // Restore register lds.l @SP+, macl lds.l @SP+, mach mov.l @SP+, r7 mov.l @SP+, r3 mov.l @SP+, r2 mov.l @SP+, r1 mov.l @SP+, r0 mov.l P_SR_BLOCK, r4 // Exception block ldc r4, sr // Switch register banks. /* SR.BL=1, SR.RB=1, SR.I=15 */ mov.l @ISP+, SP // Turn back stack ldc.l @ISP+, r6_bank // Restore register ldc.l @ISP+, r5_bank ldc.l @ISP+, r4_bank INT_RETURN asmTmpPageFaultHdr /* Entry address of BMS default handler */ .comm Csym(DefaultHandlerEntry), 4, 4 .balign 4 P_STACKTOP: .long PAGEFAULTHDR_STACKTOP P_STACKLIMIT: .long pagefaulthdr_stack P_EXPEVT: .long EXPEVT P_TEA: .long TEA P_MMUCR: .long MMUCR P_DEFHDR: .long Csym(DefaultHandlerEntry) P_HDRENT: .long Csym(PageFaultHdr) P_TMPHDR: .long Csym(TmpPageFaultHdr) P_SR_NOBLOCK: .long SR_MD | SR_I(15) P_SR_NOBL_RB: .long SR_MD | SR_I(15) | SR_RB P_SR_BLOCK: .long SR_MD | SR_I(15) | SR_RB | SR_BL/* * TLB miss exception handler * All processing has to be performed without changing the exception block (SR.BL=1). */ .text .balign 2 .globl Csym(asmTLBMissHdr) .type Csym(asmTLBMissHdr), @functionCsym(asmTLBMissHdr): /* SR.BL=1, SR.RB=1 */ mov.l r0, @-ISP // Save work register. mov.l r8, @-ISP mov.l r9, @-ISP mov.l T_PTEH, r7 mov #-22, r0 mov.l @r7, r8 mov #10, r7 mov r8, r9 shld r0, r8 // r8 = Page directory index shld r7, r9 shld r0, r9 // r9 = Page table index mov #NUM_PDIR_ENTRIES, r0 mov.l T_TTB, r7 cmp/ge r0, r8 bf l_localspace mov.l T_SATB, r7 l_localspace: mov.l @r7, r0 // r0 = Page directory movt r7 // r7 = 1:Shared space 0:Unique space tst r0, r0 // If TTB or SATB is NULL, the address is invalid. bt l_notpresent shll2 r8 mov.l @(r0, r8), r0 mov.l T_PBIT, r8 tst r8, r0 // Check the existence of page table. bt l_notpresent mov.l T_PFAMSK, r8 and r8, r0 // r0 = Page table shll2 r9 add r0, r9 mov.l @r9, r0 // r0 = PTE mov.l T_PBIT, r8 tst r8, r0 // Check the existence of page. bt l_notpresent or #PT_Accessed, r0 mov.l r0, @r9 // Update access bit. l_loadtlb: mov.l T_TLBMSK, r8 and r8, r0 // Omit bits used by OS. shll r7 // Set shared bits. add #TLB_PageSize4K, r7 // Set page size 4KB (fixed) or r7, r0 // r0 = TLB loading value mov.l T_PTEL, r7 mov.l r0, @r7 ldtlb // Load into TLB. mov.l @ISP+, r9 // Restore work register. mov.l @ISP+, r8 mov.l @ISP+, r0 rte nop l_notpresent: bra l_loadtlb mov #PTE_NONE, r0 // Invalid PTE .balign 4 T_SATB: .long Csym(SATB) T_TTB: .long TTB T_PTEH: .long PTEH T_PTEL: .long PTEL T_PBIT: .long PT_Present T_PFAMSK: .long PT_Address T_TLBMSK: .long TLB_MASK/* * TLB exception handler for re-startup processing * TLB TLB invalid exception (read) * TLB TLB miss exception */ .text .balign 2 .globl Csym(warmBootTLBInvRHdr) .globl Csym(warmBootTLBMissHdr) .type Csym(warmBootTLBInvRHdr), @function .type Csym(warmBootTLBMissHdr), @functionCsym(warmBootTLBInvRHdr): mov.l @ISP+, r0 // R0 Restore ldc.l @ISP+, spc // SPC Restore ldc.l @ISP+, ssr // SSR Restore mov.l @ISP+, MDR // MDR RestoreCsym(warmBootTLBMissHdr): /* SR.BL=1, SR.RB=1 */ mov.l r0, @-ISP // Save register mov.l r8, @-ISP mov.l r9, @-ISP mov.l W_PTEH, r7 mov #-22, r0 mov.l @r7, r8 mov #10, r7 mov r8, r9 shld r0, r8 // r8 = Page directory index shld r7, r9 shld r0, r9 // r9 = Page table index mov.l W_TTB, r7 mov.l @r7, r0 // r0 = Page directory shll2 r8 mov.l @(r0, r8), r0 mov.l W_PFAMSK, r8 and r8, r0 // r0 = Page table shll2 r9 mov.l W_TLBMSK, r7 mov.l @(r0, r9), r0 // r0 = PTE and r7, r0 // Omit bits used by OS. or #TLB_PageSize4K|TLB_Share, r0 // Set shared page size. mov.l W_PTEL, r7 mov.l r0, @r7 ldtlb // Load into TLB. mov.l @ISP+, r9 mov.l @ISP+, r8 mov.l @ISP+, r0 rte nop .balign 4 W_PTEH: .long PTEH W_PTEL: .long PTEL W_TTB: .long TTB W_PFAMSK: .long PT_Address W_TLBMSK: .long TLB_MASK/* ------------------------------------------------------------------------ *//* * Switch logical spaces * UW r2 = changeLogicalSpace( UW r5 = pteh ) * For register r5, specify "pteh = lsid". * To register r2, return PTEH before change. * Registers r1, r2 and r5 are destroyed. The other registers are saved. */ .text .balign 2 .type changeLogicalSpace, @functionchangeLogicalSpace: mov.l S_PTEH, r1 mov.l @r1, r2 // r2 = Save PTEH before change. mov.l r5, @r1 // Change PTEH extu.b r5, r5 mov #NUM_PDIR_ENTRIES_SHIFT + 2, r1 shld r1, r5 mov.l S_UATB, r1 mov.l @r1, r1 add r1, r5 mov.l S_TTB, r1 mov.l r5, @r1 // Change TTB rts nop .balign 4 S_UATB: .long Csym(UATB) S_PTEH: .long PTEH S_TTB: .long TTB/* ------------------------------------------------------------------------ *//* * Cache-related * * In cache control, the program itself needs to be a non-cache area. * Therefore, run the program using a shadow image in P2 area. *//* * Flush memory cache (both instruction/data caches) * void _ExtFlushCache( VP laddr, UW lsid ) * Flush (write back) a page (4KB) that contains laddr and cancel it. * Do not specify an invalid page (PTE.p=0). */ .text .balign 2 .globl Csym(_ExtFlushCache) .type Csym(_ExtFlushCache), @functionCsym(_ExtFlushCache): sts.l pr, @-SP mov.l C_PageMask, r0 and r0, r4 // r4 = Page start address stc sr, r3 // r3 = SR Save mov.l C_SR_DisInt, r0 ldc r0, sr bsr changeLogicalSpace // Switch logical spaces nop // r2 = Save PTEH (logical space ID) mov.l C_GOTO_P2, r0 braf r0 // Jump to P2 area. nop mov.l C_CArray, r0 mov.l C_PageSize, r1 mov.l C_CTagMask, r6 fc_loop: add #-CACHE_LINESZ, r1 mov r4, r7 // r4 = laddr or r1, r7 // r1 = ent and r6, r7 // (laddr | ent) & TagMask mov.l r7, @(r0, r1) // Write back and cancel tst r1, r1 bf fc_loop bsr changeLogicalSpace // Turn back logical space. mov r2, r5 ldc r3, sr // Reset interrupt-disabled state (to original state) lds.l @SP+, pr rts nop .balign 4 C_CArray: .long CACHE_ADR_TOP | CACHE_A C_CTagMask: .long CACHE_TAG C_PageSize: .long PAGESIZE C_PageMask: .long ~(PAGESIZE-1) C_SR_DisInt: .long SR_MD | SR_I(15) C_GOTO_P2: .long 0x20000000/* ------------------------------------------------------------------------ *//* * TLB-related *//* * Purge the whole TLB * void PurgeAllTLB( void ) */ .text .balign 2 .globl Csym(PurgeAllTLB) .type Csym(PurgeAllTLB), @functionCsym(PurgeAllTLB): stc sr, r3 // r3 = SR Save mov.l T_SR_DisInt, r0 ldc r0, sr // Interrupt-disabled mov #MMUCR, r1 mov.l @r1, r0 or #MMU_TF, r0 mov.l r0, @r1 // MMUCR TF=1 nop ldc r3, sr // Reset interrupt-disabled state (to original state) rts nop/* * Load into TLB * void _LoadTLB( VP laddr, UW lsid, UW pte, UW mmucr ) * Laddr must be located at the start of page. * The current logical space must match lsid. * Called in interrupt-disabled state and used for TLB exception handler only. */ .text .balign 2 .globl Csym(_LoadTLB) .type Csym(_LoadTLB), @functionCsym(_LoadTLB): mov.l T_TLB_MASK, r0 mov.l T_SharedSpace, r1 and r6, r0 // r6 = pte cmp/hs r1, r4 bf/s lt_localspace or #TLB_PageSize4K, r0 // Specify page size (fixed at 4KB). or #TLB_Share, r0 // Specify shared state. lt_localspace: or r4, r5 // laddr | lsid mov.l T_MMU_Base, r1 mov.l r7, @(MMUCR - MMU_Base, r1) // Specify "MMUCR = RC". mov.l r5, @(PTEH - MMU_Base, r1) // PTEH = laddr | lsid mov.l r0, @(PTEL - MMU_Base, r1) // PTEL = pte ldtlb nop rts nop .balign 4 T_MMU_Base: .long MMU_Base T_TLB_MASK: .long TLB_MASK T_SharedSpace: .long LOCALSPACE_END T_SR_DisInt: .long SR_MD | SR_I(15)/* ------------------------------------------------------------------------ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -