📄 cachealib.s
字号:
# endif /* ((CPU == PPC405) || (CPU == PPC405F)) */ /* enable instruction cache */ mtspr ICCR, p2 /* load ICCR with p2 */ isync b cacheArchOK /* return OK */cachePpc403DataEnable:# if (CPU == PPC403) lis p2, HIADJ(ppc403DccrVal) lwz p2, LO(ppc403DccrVal)(p2) /* load ppc403DccrVal value */# else /* PPC403 */ /* * if the MMU is enabled, the only way to enable the cache is * via the MMU. */ mfmsr p2 rlwinm. p2, p2, 0, _PPC_MSR_BIT_DR, _PPC_MSR_BIT_DR bne cacheArchError /* return ERROR if DR set */ lis p2, HIADJ(ppc405DccrVal) lwz p2, LO(ppc405DccrVal)(p2) /* load ppc405DccrVal value */# endif /* PPC403 */ mfspr p1, DCCR /* move DCCR to P1 */ cmpw p1, p2 /* if data cache is already */ beq cacheArchOK /* enabled just return OK */ /* reset the data cache */ li p0, 0 /* clear p0 */# if ( (CPU != PPC405F) && (CPU != PPC405) ) li p1, _DCACHE_LINE_NUM /* load number of cache lines */ slw p1, p1, p3 /* adjust with mult. factor */# else /* !405F && !405 */ lis p1, HIADJ(ppc405DCACHE_LINE_NUM) lwz p1, LO(ppc405DCACHE_LINE_NUM)(p1)# endif /* !405F && !405 */ mtctr p1# if ( (CPU == PPC405F) || (CPU == PPC405) ) /* On the PPC405 the cache line size may be variable, so read * in the variable which specifies the cache line size. */ lis p1, HIADJ(ppc405CACHE_ALIGN_SIZE) lwz p1, LO(ppc405CACHE_ALIGN_SIZE)(p1)# endif /* PPC405F || PPC405 */cachePpc403DInvalidate: dccci r0, p0# if ( (CPU == PPC405F) || (CPU == PPC405) ) add p0, p0, p1 /* bump to next line */# else /* PPC405F || PPC405 */ addi p0, p0, _CACHE_ALIGN_SIZE /* bump to next line */# endif /* PPC405F || PPC405 */ bdnz cachePpc403DInvalidate /* go to invalidate */ /* enable data cache */ mtspr DCCR, p2 /* load DCCR with p2 */# if (CPU != PPC403)/* XXX - Should set _PPC405_DCWR the same as _PPC405_DCCR if * XXX - cacheDataMode is CACHE_WRITETHROUGH -- see SPR 77774. * XXX - Not done yet because WT should also affect the TLB. */#endif /* PPC403 */ isync b cacheArchOK /* return OK *//* **** cachePpcEnable **** */#elif (CPU == PPC440) b cache440Enable/* **** cachePpcEnable **** */#else /* the following code is for 6xx other than 601 */ mfspr p1, HID0 /* move HID0 to P1 */ /* Select if the cache to enable is the Data or the Instruction cache */ cmpwi p0, _DATA_CACHE /* if _DATA_CACHE then*/ beq cachePpcDataEnable /* enable Data Cache */ /* enable an flush the Instruction cache */ andi. p2, p1, _PPC_HID0_ICE /* if instr. cache is already */ bne cacheArchOK /* enabled just return OK */ ori p1, p1, _PPC_HID0_ICE | _PPC_HID0_ICFI /* set ICE & ICFI bit */# if ((CPU == PPC603) || (CPU == PPCEC603)) rlwinm p2, p1, 0, 21, 19 /* clear the ICFI bit */# endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ /* * The setting of the instruction cache enable (ICE) bit must be * preceded by an isync instruction to prevent the cache from being * enabled or disabled while an instruction access is in progress. * XXX TPR to verify. */ isync /* Synchronize for ICE enable */ mtspr HID0, p1 /* Enable Instr Cache & Inval cache */# if ((CPU == PPC603) || (CPU == PPCEC603)) mtspr HID0, p2 /* using 2 consec instructions */ isync /* PPC603 recommendation */# else /* ((CPU == PPC603) || (CPU == PPCEC603)) */ sync /* sync here makes no sense, but isync * does not seem to work properly on * any of 604e, 750CX, 750FX, 7400 */# endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ b cacheArchOK /* return OK */cachePpcDataEnable: /* enable data cache code */ andi. p2, p1, _PPC_HID0_DCE /* if data cache already enabled */ bne cacheArchOK /* then exit with OK */ ori p1, p1, _PPC_HID0_DCE | _PPC_HID0_DCFI /* set DCE & DCFI bit */# if ((CPU == PPC603) || (CPU == PPCEC603)) rlwinm p2, p1, 0, 22, 20 /* clear the DCFI bit */# endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ /* * The setting of the data cache enable (DCE) bit must be * preceded by a sync instruction to prevent the cache from * being enabled or disabled during a data access. */ sync /* Synchronize for DCE enable */ mtspr HID0, p1 /* Enable Data Cache & Inval cache */# if ((CPU == PPC603) || (CPU == PPCEC603)) mtspr HID0, p2 /* using 2 consecutive instructions */ /* PPC603 recommendation */# endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ sync b cacheArchOK /* return OK *//* **** cachePpcEnable **** */#endif /* (CPU == PPC85XX) */FUNC_END(cachePpcEnable)/******************************************************************************** cachePpcDisable - Disable the PowerPC Instruction or Data cache.** This routine disables the instruction or data cache as selected by the* <cache> argument.** NOTE:* This routine should not be called by the user application. Only* the cacheArchDisable() can call this routine.** RETURNS: OK, or ERROR if the cache can not be disabled.** SEE ALSO:*.I "PPC403GA Embedded Controller User's Manual"*.I "PowerPC 601 RISC Microprocessor User's Manual"*.I "PowerPC 603 RISC Microprocessor User's Manual"*.I "PowerPC 604 RISC Microprocessor User's Manual"* STATUS cachePpcDisable* (* CACHE_TYPE cache, /@ cache to disable @/* )*/FUNC_BEGIN(cachePpcDisable)#if (CPU == PPC85XX) b cacheE500Disable#elif (CPU == PPC601)/* * This #if block covers the entire cachePpcDisable function. * All alternatives are marked as just below. *//* **** cachePpcDisable **** */ /* * PPC601 caches are always on. The only way to disable the caches is * via the MMU. */ b cacheArchError /* return ERROR *//* **** cachePpcDisable **** */#elif ( (CPU == PPC403) || (CPU == PPC405) || (CPU == PPC405F) )# if (CPU == PPC403) li p1, 0 /* p1 = shift-left count for */ mfspr p2, PVR /* _CACHE_LINE_NUM per 403 CPU type */ rlwinm p2, p2, 24, 24, 31 /* extract CPU ID PVR[16:23] bits */ cmpwi p2, _PVR_CONF_403GCX bne disableNo403gcx li p1, 3 /* 403GCX has cache 8 times larger */disableNo403gcx:# endif /* PPC403 */ cmpwi p0, _DATA_CACHE /* if _DATA_CACHE then*/ beq cachePpc403DataDisable /* disable Data Cache */ /* disable instruction cache */# if ( CPU == PPC405 || CPU == PPC405F ) /* * if the MMU is enabled, the only way to disable the cache is * via the MMU. */ mfmsr p0 rlwinm. p0, p0, 0, _PPC_MSR_BIT_IR, _PPC_MSR_BIT_IR bne cacheArchError /* return ERROR if IR set */# endif /* 405 || 405F */ li p0, 0x0 /* 0x0-0xffffffff non cacheable */ mtspr ICCR, p0 isync b cacheArchOK /* return OK */ /* disable data cache */cachePpc403DataDisable:# if ( (CPU != PPC405F) && (CPU != PPC405) ) li p3, _DCACHE_LINE_NUM /* # of cache lines in most 403 */ slw p3, p3, p1 /* 403GCX has 8x as many */# else /* !405F && !405 */ /* * if the MMU is enabled, the only way to disable the cache is * via the MMU. */ mfmsr p3 rlwinm. p3, p3, 0, _PPC_MSR_BIT_DR, _PPC_MSR_BIT_DR bne cacheArchError /* return ERROR if DR set */ lis p3, HIADJ(ppc405DCACHE_LINE_NUM) lwz p3, LO(ppc405DCACHE_LINE_NUM)(p3)# endif /* !405F && !405 */ mtspr CTR, p3 /* CTR = # of cache lines */ slwi p5, p3, 5 /* p5 = # of bytes in one cache way */ /* * load up p2 with the buffer address minus * one cache block size */# if (CPU == PPC403) lis p2, HI(cachePpcReadOrigin - _CACHE_ALIGN_SIZE) ori p2,p2,LO(cachePpcReadOrigin - _CACHE_ALIGN_SIZE)# else /* PPC403 */ lis p4, HIADJ(ppc405CACHE_ALIGN_SIZE) lwz p4, LO(ppc405CACHE_ALIGN_SIZE)(p4) lis p3, HIADJ(cachePpcReadOrigin) lwz p3, LO(cachePpcReadOrigin)(p3) /* buffer points to 0x10000 - text segment */ subf p2, p4, p3# endif /* PPC403 */ /* * Disable interrupts during flush, to ensure everything * is marked invalid when cache is disabled. */ mfmsr p1 /* read msr */ INT_MASK(p1, p0) /* mask off ce & ee bits */ mtmsr p0 /* DISABLE INTERRUPT */cachePpc403DisableFlush: /* * The dcbf instruction seems to mark the flushed line as least- * recently-used, so just cycling through will only flush one * way of each congruence class no matter how many iterations are * performed. To fix this, we load up both ways from different * addresses before flushing them both. This code will only work * on a two-way cache (which covers all 403 and 405, including * 403GCX and 405GPr). */# if ( (CPU == PPC405F) || (CPU == PPC405) ) add p2, p4, p2 lwz p3, 0(p2) /* cast out old line if modified */ lwzx p3, p2, p5 /* repeat p5 higher for other way */# else /* PPC405F || PPC405 */ lbzu p4, _CACHE_ALIGN_SIZE(p2) /* cast out old line if modified */ lbzx p4, p2, p5 /* repeat p5 higher for other way */# endif /* PPC405F || PPC405 */ dcbf 0, p2 /* flush 1st newly-loaded line */ dcbf p2, p5 /* flush 2nd newly-loaded line */ bdnz cachePpc403DisableFlush sync /* disable the data cache */ li p0, 0x0 /* 0x0-0xffffffff non cacheable */ mtspr DCWR, p0 /* must also turn off WT bits */ mtspr DCCR, p0 sync mtmsr p1 /* restore MSR -- ENABLE INTERRUPT */ b cacheArchOK /* return OK *//* **** cachePpcDisable **** */#elif (CPU == PPC440) b cache440Disable/* **** cachePpcDisable **** */#else /* ((CPU == PPC603) || (CPU == PPCEC603) || (CPU == PPC604)) */ mfspr p1, HID0 /* save HID0 to p1 */ cmpwi p0, _DATA_CACHE /* <cache> == _DATA_CACHE ? */ beq cachePpcDataDisable /* disable instruction cache */ rlwinm. p2, p1, 0, _PPC_HID0_BIT_ICE, _PPC_HID0_BIT_ICE beq cacheArchOK /* return OK if cache already off */ ori p2,p1,_PPC_HID0_ICFI /* set the ICFI bit */ rlwinm p1,p1,0,21,19 /* Turn off the ICFI bit */ rlwinm p1,p1,0,17,15 /* Turn off Cache enable bit */ isync /* Synchronize for ICE disable */ mtspr HID0,p2 /* Invalidate Instr Cache */# if ((CPU == PPC603) || (CPU == PPCEC603)) mtspr HID0,p1 /* using 2 consec instructions */ isync /* PPC603 recommendation */# else /* ((CPU == PPC603) || (CPU == PPCEC603)) */ sync /* sync here makes no sense, but isync * does not seem to work properly on * any of 604e, 750CX, 750FX, 7400 */# endif /* ((CPU == PPC603) || (CPU == PPCEC603)) */ b cacheArchOK /* return OK */ /* disable data cache */cachePpcDataDisable: /* if cache already disabled, just return OK */ rlwinm. p2, p1, 0, _PPC_HID0_BIT_DCE, _PPC_HID0_BIT_DCE beq cacheArchOK /* * All 7xx and 74xx require interrupts disabled during flush. * Do it for 603/604 also, to ensure everything is marked invalid * when cache is disabled. * Also disable the MMU so that TLB reloads (hardware or software) * do not cause page table entries to be brought into the cache. */#define _PPC604_USE_DCFA mfmsr p0 /* read msr */ INT_MASK(p0, p4) /* mask off ee bit */ rlwinm p4, p4, 0, 28, 25 /* mask off DR and IR */ mtmsr p4 /* DISABLE INTERRUPT & MMU */# if (CPU == PPC604) mfspr p2,PVR rlwinm p2,p2,16,16,31 /* extract MS half of PVR */ cmplwi p2,0x0009 /* check for PPC604e */ beq cachePpcDataDisable604 cmplwi p2,0x0004 /* check for PPC604 */ beq cachePpcDataDisable604 cmplwi p2,0x8000 /* check for MPC7450 */ beq cachePpcDataDisable604 /* Like 604, 7450 has no DCFA */ /* 7400 and 7410 (but not 744x or 745x) have a hardware L1 flush */ rlwinm p2,p2,0,17,31 /* mask off bit 0x8000 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -