URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [lib/] [libbsp/] [mips64orion/] [p4000/] [startup/] [idtmem.S] - Rev 1765
Compare with Previous | Blame | View Log
/*Based upon IDT provided code with the following release:This source code has been made available to you by IDT on an AS-ISbasis. Anyone receiving this source is licensed under IDT copyrightsto use it in any way he or she deems fit, including copying it,modifying it, compiling it, and redistributing it either with orwithout modifications. No license under IDT patents or patentapplications is to be implied by the copyright license.Any user of this software should understand that IDT cannot providetechnical support for this software and will not be responsible forany consequences resulting from the use of this software.Any person who transfers this source code or any derivative work mustinclude the IDT copyright notice, this paragraph, and the preceedingtwo paragraphs in the transferred software.COPYRIGHT IDT CORPORATION 1996LICENSED MATERIAL - PROGRAM PROPERTY OF IDTidtmem.S,v 1.4 1999/03/31 23:21:19 joel Exp*//**************************************************************************** idtmem.s - memory and cache functions**** Copyright 1991 Integrated Device Technology, Inc.** All Rights Reserved****************************************************************************//** 950313: Ketan fixed bugs in mfc0/mtc0 hazards, and removed hack* to set mem_size.*/#include <iregdef.h>#include <idtcpu.h>#include <idtmon.h>.datamem_size:.word 0dcache_size:.word 0icache_size:#if defined(CPU_R3000).word MINCACHE#endif#if defined(CPU_R4000).word 0#endif#if defined(CPU_R4000).datascache_size:.word 0icache_linesize:.word 0dcache_linesize:.word 0scache_linesize:.word 0#endif.text#if defined (CPU_R3000)#define CONFIGFRM ((2*4)+4)/***************************************************************************** Config_Dcache() -- determine size of Data cache****************************************************************************/FRAME(config_Dcache,sp, CONFIGFRM, ra).set noreordersubu sp,CONFIGFRMsw ra,CONFIGFRM-4(sp) /* save return address */sw s0,4*4(sp) /* save s0 in first regsave slot */mfc0 s0,C0_SR /* save SR */nopmtc0 zero,C0_SR /* disable interrupts */.set reorderjal _size_cache /* returns Data cache size in v0 */sw v0, dcache_size /* save it */and s0, ~SR_PE /* do not clear PE */.set noreordermtc0 s0,C0_SR /* restore SR */nop.set reorderlw s0, 4*4(sp) /* restore s0 */lw ra,CONFIGFRM-4(sp) /* restore ra */addu sp,CONFIGFRM /* pop stack */j raENDFRAME(config_Dcache)/***************************************************************************** Config_Icache() -- determine size of Instruction cache** MUST be run in uncached mode/handled in idt_csu.s****************************************************************************/FRAME(config_Icache,sp, CONFIGFRM, ra).set noreordersubu sp,CONFIGFRMsw ra,CONFIGFRM-4(sp) /* save return address */sw s0,4*4(sp) /* save s0 in first regsave slot */mfc0 s0,C0_SR /* save SR */nopmtc0 zero, C0_SR /* disable interrupts */li v0,SR_SWC /* swap caches/disable ints */mtc0 v0,C0_SRnop.set reorderjal _size_cache /* returns instruction cache size */.set noreordermtc0 zero,C0_SR /* swap back caches */nopand s0,~SR_PE /* do not inadvertantly clear PE */mtc0 s0,C0_SR /* restore SR */nop.set reordersw v0, icache_size /* save it AFTER caches back */lw s0,4*4(sp) /* restore s0 */lw ra,CONFIGFRM-4(sp) /* restore ra */addu sp,CONFIGFRM /* pop stack */j raENDFRAME(config_Icache)/**************************************************************************** _size_cache()** returns cache size in v0**************************************************************************/FRAME(_size_cache,sp,0,ra).set noreordermfc0 t0,C0_SR /* save current sr */nopand t0,~SR_PE /* do not inadvertently clear PE */or v0,t0,SR_ISC /* isolate cache */mtc0 v0,C0_SR/** First check if there is a cache there at all*/move v0,zeroli v1,0xa5a5a5a5 /* distinctive pattern */sw v1,K0BASE /* try to write into cache */lw t1,K0BASE /* try to read from cache */nopmfc0 t2,C0_SRnop.set reorderand t2,SR_CMbne t2,zero,3f /* cache miss, must be no cache */bne v1,t1,3f /* data not equal -> no cache *//** Clear cache size boundries to known state.*/li v0,MINCACHE1:sw zero,K0BASE(v0)sll v0,1ble v0,MAXCACHE,1bli v0,-1sw v0,K0BASE(zero) /* store marker in cache */li v0,MINCACHE /* MIN cache size */2: lw v1,K0BASE(v0) /* Look for marker */bne v1,zero,3f /* found marker */sll v0,1 /* cache size * 2 */ble v0,MAXCACHE,2b /* keep looking */move v0,zero /* must be no cache */.set noreorder3: mtc0 t0,C0_SR /* restore sr */j ranopENDFRAME(_size_cache).set reorder#define FLUSHFRM (2*4)/******************************************************************************* flush_Dcache() - flush entire Data cache******************************************************************************/FRAME(flush_Dcache,sp,FLUSHFRM,ra)lw t2, dcache_size.set noreordermfc0 t3,C0_SR /* save SR */nopand t3,~SR_PE /* dont inadvertently clear PE */beq t2,zero,_Dflush_done /* no D cache, get out! */nopli v0, SR_ISC /* isolate cache */mtc0 v0, C0_SRnop.set reorderli t0,K0BASE /* set loop registers */or t1,t0,t22: sb zero,0(t0)sb zero,4(t0)sb zero,8(t0)sb zero,12(t0)sb zero,16(t0)sb zero,20(t0)sb zero,24(t0)addu t0,32sb zero,-4(t0)bne t0,t1,2b.set noreorder_Dflush_done:mtc0 t3,C0_SR /* restore Status Register */.set reorderj raENDFRAME(flush_Dcache)/******************************************************************************* flush_Icache() - flush entire Instruction cache**** NOTE: Icache can only be flushed/cleared when uncached** Code forces into uncached memory regardless of calling mode******************************************************************************/FRAME(flush_Icache,sp,FLUSHFRM,ra)lw t1,icache_size.set noreordermfc0 t3,C0_SR /* save SR */nopla v0,1fli v1,K1BASEor v0,v1j v0 /* force into non-cached space */nop1:and t3,~SR_PE /* dont inadvertently clear PE */beq t1,zero,_Iflush_done /* no i-cache get out */nopli v0,SR_ISC|SR_SWC /* disable intr, isolate and swap */mtc0 v0,C0_SRli t0,K0BASE.set reorderor t1,t0,t11: sb zero,0(t0)sb zero,4(t0)sb zero,8(t0)sb zero,12(t0)sb zero,16(t0)sb zero,20(t0)sb zero,24(t0)addu t0,32sb zero,-4(t0)bne t0,t1,1b.set noreorder_Iflush_done:mtc0 t3,C0_SR /* un-isolate, enable interrupts */.set reorderj raENDFRAME(flush_Icache)/****************************************************************************** clear_Dcache(base_addr, byte_count) - flush portion of Data cache**** a0 = base address of portion to be cleared** a1 = byte count of length*****************************************************************************/FRAME(clear_Dcache,sp,0,ra)lw t2, dcache_size /* Data cache size */.set noreordermfc0 t3,C0_SR /* save SR */nopand t3,~SR_PE /* dont inadvertently clear PE */nopnop.set reorder/** flush data cache*/.set noreordernopli v0,SR_ISC /* isolate data cache */mtc0 v0,C0_SR.set reorderbltu t2,a1,1f /* cache is smaller than region */move t2,a11: addu t2,a0 /* ending address + 1 */move t0,a01: sb zero,0(t0)sb zero,4(t0)sb zero,8(t0)sb zero,12(t0)sb zero,16(t0)sb zero,20(t0)sb zero,24(t0)addu t0,32sb zero,-4(t0)bltu t0,t2,1b.set noreordermtc0 t3,C0_SR /* un-isolate, enable interrupts */nop.set reorderj raENDFRAME(clear_Dcache)/****************************************************************************** clear_Icache(base_addr, byte_count) - flush portion of Instruction cache**** a0 = base address of portion to be cleared** a1 = byte count of length**** NOTE: Icache can only be flushed/cleared when uncached** Code forces into uncached memory regardless of calling mode*****************************************************************************/FRAME(clear_Icache,sp,0,ra)lw t1, icache_size /* Instruction cache size *//** flush text cache*/.set noreordermfc0 t3,C0_SR /* save SR */nopla v0,1fli v1,K1BASEor v0,v1j v0 /* force into non-cached space */nop1:and t3,~SR_PE /* dont inadvertently clear PE */nopnopli v0,SR_ISC|SR_SWC /* disable intr, isolate and swap */mtc0 v0,C0_SR.set reorderbltu t1,a1,1f /* cache is smaller than region */move t1,a11: addu t1,a0 /* ending address + 1 */move t0,a0sb zero,0(t0)sb zero,4(t0)sb zero,8(t0)sb zero,12(t0)sb zero,16(t0)sb zero,20(t0)sb zero,24(t0)addu t0,32sb zero,-4(t0)bltu t0,t1,1b.set noreordermtc0 t3,C0_SR /* un-isolate, enable interrupts */nopnopnop /* allow time for caches to swap */.set reorderj raENDFRAME(clear_Icache)/****************************************************************************** get_mem_conf - get memory configuration*****************************************************************************/FRAME(get_mem_conf,sp,0,ra)lw t6, mem_sizesw t6, 0(a0)lw t7, icache_sizesw t7, 4(a0)lw t8, dcache_sizesw t8, 8(a0)j raENDFRAME(get_mem_conf)#endif /* defined CPU_R3000 */#if defined(CPU_R4000)#define LEAF(label) FRAME(label,sp,0,ra)#define XLEAF(label) \.globl label ; \label:#define END(label) ENDFRAME(label)/** cacheop macro to automate cache operations* first some helpers...*/#define _mincache(size, maxsize) \bltu size,maxsize,8f ; \move size,maxsize ; \8:#define _align(tmp, minaddr, maxaddr, linesize) \subu tmp,linesize,1 ; \not tmp ; \and minaddr,tmp ; \addu maxaddr,-1 ; \and maxaddr,tmp/* This is a bit of a hack really because it relies on minaddr=a0 */#define _doop1(op1) \cache op1,0(a0)#define _doop2(op1, op2) \cache op1,0(a0) ; \cache op2,0(a0)/* specials for cache initialisation */#define _doop1lw1(op1) \cache op1,0(a0) ; \lw zero,0(a0) ; \cache op1,0(a0)#define _doop121(op1,op2) \cache op1,0(a0) ; \nop; \cache op2,0(a0) ; \nop; \cache op1,0(a0)#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \.set noreorder ; \7: _doop##tag##ops ; \bne minaddr,maxaddr,7b ; \addu minaddr,linesize ; \.set reorder/* finally the cache operation macros */#define icacheopn(kva, n, cache_size, cache_linesize, tag, ops) \_mincache(n, cache_size); \blez n,9f ; \addu n,kva ; \_align(t1, kva, n, cache_linesize) ; \_oploopn(kva, n, cache_linesize, tag, ops) ; \9:#define vcacheopn(kva, n, cache_size, cache_linesize, tag, ops) \blez n,9f ; \addu n,kva ; \_align(t1, kva, n, cache_linesize) ; \_oploopn(kva, n, cache_linesize, tag, ops) ; \9:#define icacheop(kva, n, cache_size, cache_linesize, op) \icacheopn(kva, n, cache_size, cache_linesize, 1, (op))#define vcacheop(kva, n, cache_size, cache_linesize, op) \vcacheopn(kva, n, cache_size, cache_linesize, 1, (op)).text/** static void _size_cache() R4000** Internal routine to determine cache sizes by looking at R4000 config* register. Sizes are returned in registers, as follows:* t2 icache size* t3 dcache size* t6 scache size* t4 icache line size* t5 dcache line size* t7 scache line size*/LEAF(_size_cache)mfc0 t0,C0_CONFIGand t1,t0,CFG_ICMASKsrl t1,CFG_ICSHIFTli t2,0x1000sll t2,t1and t1,t0,CFG_DCMASKsrl t1,CFG_DCSHIFTli t3,0x1000sll t3,t1li t4,32and t1,t0,CFG_IBbnez t1,1fli t4,161:li t5,32and t1,t0,CFG_DBbnez t1,1fli t5,161:move t6,zero # default to no scachemove t7,zero #and t1,t0,CFG_C_UNCACHED # test config registerbnez t1,1f # no scache if uncached/non-coherentli t6,0x100000 # assume 1Mb scache <<-NOTEand t1,t0,CFG_SBMASKsrl t1,CFG_SBSHIFTli t7,16sll t7,t11: j raEND(_size_cache)/** void config_cache() R4000** Work out size of I, D & S caches, assuming they are already initialised.*/LEAF(config_cache)lw t0,icache_sizebgtz t0,8f # already known?move v0,rabal _size_cachemove ra,v0sw t2,icache_sizesw t3,dcache_sizesw t6,scache_sizesw t4,icache_linesizesw t5,dcache_linesizesw t7,scache_linesize8: j raEND(config_cache)/** void _init_cache() R4000*/LEAF(_init_cache)/** First work out the sizes*/move v0,rabal _size_cachemove ra,v0/** The caches may be in an indeterminate state,* so we force good parity into them by doing an* invalidate, load/fill, invalidate for each line.*//* disable all i/u and cache exceptions */mfc0 v0,C0_SRand v1,v0,~SR_IEor v1,SR_DEmtc0 v1,C0_SRmtc0 zero,C0_TAGLOmtc0 zero,C0_TAGHI/* assume bottom of RAM will generate good parity for the cache */li a0,PHYS_TO_K0(0)move a2,t2 # icache_sizemove a3,t4 # icache_linesizemove a1,a2icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill_I))li a0,PHYS_TO_K0(0)move a2,t3 # dcache_sizemove a3,t5 # dcache_linesizemove a1,a2icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_D))/* assume unified I & D in scache <<-NOTE */blez t6,1fli a0,PHYS_TO_K0(0)move a2,t6move a3,t7move a1,a2icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_SD))1: mtc0 v0,C0_SRj raEND(_init_cache)/** void flush_cache (void) R4000** Flush and invalidate all caches*/LEAF(flush_cache)/* secondary cacheops do all the work if present */lw a2,scache_sizeblez a2,1flw a3,scache_linesizeli a0,PHYS_TO_K0(0)move a1,a2icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD)b 2f1:lw a2,icache_sizeblez a2,2flw a3,icache_linesizeli a0,PHYS_TO_K0(0)move a1,a2icacheop(a0,a1,a2,a3,Index_Invalidate_I)lw a2,dcache_sizelw a3,dcache_linesizeli a0,PHYS_TO_K0(0)move a1,a2icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)2: j raEND(flush_cache)/** void flush_cache_nowrite (void) R4000** Invalidate all caches*/LEAF(flush_cache_nowrite)mfc0 v0,C0_SRand v1,v0,~SR_IEmtc0 v1,C0_SRmtc0 zero,C0_TAGLOmtc0 zero,C0_TAGHIlw a2,icache_sizeblez a2,2flw a3,icache_linesizeli a0,PHYS_TO_K0(0)move a1,a2icacheop(a0,a1,a2,a3,Index_Invalidate_I)lw a2,dcache_sizelw a3,dcache_linesizeli a0,PHYS_TO_K0(0)move a1,a2icacheop(a0,a1,a2,a3,Index_Store_Tag_D)lw a2,scache_sizeblez a2,2flw a3,scache_linesizeli a0,PHYS_TO_K0(0)move a1,a2icacheop(a0,a1,a2,a3,Index_Store_Tag_SD)2: mtc0 v0,C0_SRj raEND(flush_cache_nowrite)/** void clean_cache (unsigned kva, size_t n) R4000** Writeback and invalidate address range in all caches*/LEAF(clean_cache)XLEAF(clear_cache)/* secondary cacheops do all the work (if fitted) */lw a2,scache_sizeblez a2,1flw a3,scache_linesizevcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD)b 2f1: lw a2,icache_sizeblez a2,2flw a3,icache_linesize/* save kva & n for subsequent loop */move t8,a0move t9,a1vcacheop(a0,a1,a2,a3,Hit_Invalidate_I)lw a2,dcache_sizelw a3,dcache_linesize/* restore kva & n */move a0,t8move a1,t9vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D)2: j raEND(clean_cache)/** void clean_dcache (unsigned kva, size_t n) R4000** Writeback and invalidate address range in primary data cache*/LEAF(clean_dcache)lw a2,dcache_sizeblez a2,2flw a3,dcache_linesizevcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D)2: j raEND(clean_dcache)/** void clean_dcache_indexed (unsigned kva, size_t n) R4000** Writeback and invalidate indexed range in primary data cache*/LEAF(clean_dcache_indexed)lw a2,dcache_sizeblez a2,2flw a3,dcache_linesize#ifdef CPU_ORIONsrl a2,1 # do one set (half cache) at a timemove t8,a0 # save kva & nmove t9,a1icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)addu a0,t8,a2 # do next setmove a1,t9 # restore n#endificacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)2: j raEND(clean_dcache_indexed)/** void clean_dcache_nowrite (unsigned kva, size_t n) R4000** Invalidate an address range in primary data cache*/LEAF(clean_dcache_nowrite)lw a2,dcache_sizeblez a2,2flw a3,dcache_linesizevcacheop(a0,a1,a2,a3,Hit_Invalidate_D)2: j raEND(clean_dcache_nowrite)/** void clean_dcache_nowrite_indexed (unsigned kva, size_t n) R4000** Invalidate indexed range in primary data cache*/LEAF(clean_dcache_nowrite_indexed)mfc0 v0,C0_SRand v1,v0,~SR_IEmtc0 v1,C0_SRmtc0 zero,C0_TAGLOmtc0 zero,C0_TAGHIlw a2,dcache_sizeblez a2,2flw a3,dcache_linesize#ifdef CPU_ORIONsrl a2,1 # do one set (half cache) at a timemove t8,a0 # save kva & nmove t9,a1icacheop(a0,a1,a2,a3,Index_Store_Tag_D)addu a0,t8,a2 # do next setmove a1,t9 # restore n#endificacheop(a0,a1,a2,a3,Index_Store_Tag_D)2: mtc0 v0,C0_SRj raEND(clean_dcache_nowrite_indexed)/** void clean_icache (unsigned kva, size_t n) R4000** Invalidate address range in primary instruction cache*/LEAF(clean_icache)lw a2,icache_sizeblez a2,2flw a3,icache_linesizevcacheop(a0,a1,a2,a3,Hit_Invalidate_I)2: j raEND(clean_icache)/** void clean_icache_indexed (unsigned kva, size_t n) R4000** Invalidate indexed range in primary instruction cache*/LEAF(clean_icache_indexed)lw a2,icache_sizeblez a2,2flw a3,icache_linesize#ifdef CPU_ORIONsrl a2,1 # do one set (half cache) at a timemove t8,a0 # save kva & nmove t9,a1icacheop(a0,a1,a2,a3,Index_Invalidate_I)addu a0,t8,a2 # do next setmove a1,t9 # restore n#endificacheop(a0,a1,a2,a3,Index_Invalidate_I)2: j raEND(clean_icache_indexed)/** void clean_scache (unsigned kva, size_t n) R4000** Writeback and invalidate address range in secondary cache*/LEAF(clean_scache)lw a2,scache_sizeblez a2,2flw a3,scache_linesizevcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD)2: j raEND(clean_scache)/** void clean_scache_indexed (unsigned kva, size_t n) R4000** Writeback and invalidate indexed range in secondary cache*/LEAF(clean_scache_indexed)lw a2,scache_sizeblez a2,2flw a3,scache_linesizeicacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD)2: j raEND(clean_scache_indexed)/** void clean_scache_nowrite (unsigned kva, size_t n) R4000** Invalidate an address range in secondary cache*/LEAF(clean_scache_nowrite)lw a2,scache_sizeblez a2,2flw a3,scache_linesizevcacheop(a0,a1,a2,a3,Hit_Invalidate_SD)2: j raEND(clean_scache_nowrite)/** void clean_scache_nowrite_indexed (unsigned kva, size_t n) R4000** Invalidate indexed range in secondary cache*/LEAF(clean_scache_nowrite_indexed)mfc0 v0,C0_SRand v1,v0,~SR_IEmtc0 v1,C0_SRmtc0 zero,C0_TAGLOmtc0 zero,C0_TAGHIlw a2,scache_sizeblez a2,2flw a3,scache_linesizeicacheop(a0,a1,a2,a3,Index_Store_Tag_SD)2: mtc0 v0,C0_SRj raEND(clean_scache_nowrite_indexed)/****************************************************************************** get_mem_conf - get memory configuration R4000*****************************************************************************/FRAME(get_mem_conf,sp,0,ra)lw t6, mem_sizesw t6, 0(a0)lw t7, icache_sizesw t7, 4(a0)lw t8, dcache_sizesw t8, 8(a0)lw t7, scache_sizesw t7, 12(a0)j raENDFRAME(get_mem_conf)#endif /* defined(CPU_R4000) *//** void set_mem_size (mem_size)** config_memory()'s memory size gets written into mem_size here.* Now we don't need to call config_cache() with memory size - New to IDTC6.0*/FRAME(set_memory_size,sp,0,ra)sw a0, mem_sizej raENDFRAME(set_memory_size)
