709 lines
20 KiB
C
709 lines
20 KiB
C
|
#ifndef XTENSA_CACHEASM_H
|
||
|
#define XTENSA_CACHEASM_H
|
||
|
|
||
|
/*
|
||
|
* THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
|
||
|
*
|
||
|
* include/asm-xtensa/xtensa/cacheasm.h -- assembler-specific cache
|
||
|
* related definitions that depend on CORE configuration.
|
||
|
*
|
||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||
|
* License. See the file "COPYING" in the main directory of this archive
|
||
|
* for more details.
|
||
|
*
|
||
|
* Copyright (C) 2002 Tensilica Inc.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <xtensa/coreasm.h>
|
||
|
|
||
|
|
||
|
/*
|
||
|
* This header file defines assembler macros of the form:
|
||
|
* <x>cache_<func>
|
||
|
* where <x> is 'i' or 'd' for instruction and data caches,
|
||
|
* and <func> indicates the function of the macro.
|
||
|
*
|
||
|
* The following functions <func> are defined,
|
||
|
* and apply only to the specified cache (I or D):
|
||
|
*
|
||
|
* reset
|
||
|
* Resets the cache.
|
||
|
*
|
||
|
* sync
|
||
|
* Makes sure any previous cache instructions have been completed;
|
||
|
* ie. makes sure any previous cache control operations
|
||
|
* have had full effect and been synchronized to memory.
|
||
|
* Eg. any invalidate completed [so as not to generate a hit],
|
||
|
* any writebacks or other pipelined writes written to memory, etc.
|
||
|
*
|
||
|
* invalidate_line (single cache line)
|
||
|
* invalidate_region (specified memory range)
|
||
|
* invalidate_all (entire cache)
|
||
|
* Invalidates all cache entries that cache
|
||
|
* data from the specified memory range.
|
||
|
* NOTE: locked entries are not invalidated.
|
||
|
*
|
||
|
* writeback_line (single cache line)
|
||
|
* writeback_region (specified memory range)
|
||
|
* writeback_all (entire cache)
|
||
|
* Writes back to memory all dirty cache entries
|
||
|
* that cache data from the specified memory range,
|
||
|
* and marks these entries as clean.
|
||
|
* NOTE: on some future implementations, this might
|
||
|
* also invalidate.
|
||
|
* NOTE: locked entries are written back, but never invalidated.
|
||
|
* NOTE: instruction caches never implement writeback.
|
||
|
*
|
||
|
* writeback_inv_line (single cache line)
|
||
|
* writeback_inv_region (specified memory range)
|
||
|
* writeback_inv_all (entire cache)
|
||
|
* Writes back to memory all dirty cache entries
|
||
|
* that cache data from the specified memory range,
|
||
|
* and invalidates these entries (including all clean
|
||
|
* cache entries that cache data from that range).
|
||
|
* NOTE: locked entries are written back but not invalidated.
|
||
|
* NOTE: instruction caches never implement writeback.
|
||
|
*
|
||
|
* lock_line (single cache line)
|
||
|
* lock_region (specified memory range)
|
||
|
* Prefetch and lock the specified memory range into cache.
|
||
|
* NOTE: if any part of the specified memory range cannot
|
||
|
* be locked, a ??? exception occurs. These macros don't
|
||
|
* do anything special (yet anyway) to handle this situation.
|
||
|
*
|
||
|
* unlock_line (single cache line)
|
||
|
* unlock_region (specified memory range)
|
||
|
* unlock_all (entire cache)
|
||
|
* Unlock cache entries that cache the specified memory range.
|
||
|
* Entries not already locked are unaffected.
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/*************************** GENERIC -- ALL CACHES ***************************/
|
||
|
|
||
|
|
||
|
/*
|
||
|
* The following macros assume the following cache size/parameter limits
|
||
|
* in the current Xtensa core implementation:
|
||
|
* cache size: 1024 bytes minimum
|
||
|
* line size: 16 - 64 bytes
|
||
|
* way count: 1 - 4
|
||
|
*
|
||
|
* Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4
|
||
|
* Hence the assumption that each loop can execute four cache instructions.
|
||
|
*
|
||
|
* Correspondingly, the offset range of instructions is assumed able to cover
|
||
|
* four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for
|
||
|
* both hit and indexed cache instructions. Ie. these offsets are all
|
||
|
* valid: 0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64).
|
||
|
* This is true of all original cache instructions
|
||
|
* (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets
|
||
|
* of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2).
|
||
|
* This is also true of subsequent cache instructions
|
||
|
* (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets
|
||
|
* of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4).
|
||
|
*
|
||
|
* (Maximum cache size, currently 32k, doesn't affect the following macros.
|
||
|
* Cache ways > MMU min page size cause aliasing but that's another matter.)
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Macro to apply an 'indexed' cache instruction to the entire cache.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* cainst instruction/ that takes an address register parameter
|
||
|
* and an offset parameter (in range 0 .. 3*linesize).
|
||
|
* size size of cache in bytes
|
||
|
* linesize size of cache line in bytes
|
||
|
* assoc_or1 number of associativities (ways/sets) in cache
|
||
|
* if all sets affected by cainst,
|
||
|
* or 1 if only one set (or not all sets) of the cache
|
||
|
* is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]).
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
|
||
|
.macro cache_index_all cainst, size, linesize, assoc_or1, aa, ab
|
||
|
|
||
|
// Sanity-check on cache parameters:
|
||
|
.ifne (\size % (\linesize * \assoc_or1 * 4))
|
||
|
.err // cache configuration outside expected/supported range!
|
||
|
.endif
|
||
|
|
||
|
// \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst.
|
||
|
movi \aa, (\size / (\linesize * \assoc_or1 * 4))
|
||
|
// Possible improvement: need only loop if \aa > 1 ;
|
||
|
// however that particular condition is highly unlikely.
|
||
|
movi \ab, 0 // to iterate over cache
|
||
|
floop \aa, cachex\@
|
||
|
\cainst \ab, 0*\linesize
|
||
|
\cainst \ab, 1*\linesize
|
||
|
\cainst \ab, 2*\linesize
|
||
|
\cainst \ab, 3*\linesize
|
||
|
addi \ab, \ab, 4*\linesize // move to next line
|
||
|
floopend \aa, cachex\@
|
||
|
|
||
|
.endm
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Macro to apply a 'hit' cache instruction to a memory region,
|
||
|
* ie. to any cache entries that cache a specified portion (region) of memory.
|
||
|
* Takes care of the unaligned cases, ie. may apply to one
|
||
|
* more cache line than $asize / lineSize if $aaddr is not aligned.
|
||
|
*
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* cainst instruction/macro that takes an address register parameter
|
||
|
* and an offset parameter (currently always zero)
|
||
|
* and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.)
|
||
|
* linesize_log2 log2(size of cache line in bytes)
|
||
|
* addr register containing start address of region (clobbered)
|
||
|
* asize register containing size of the region in bytes (clobbered)
|
||
|
* askew unique register used as temporary
|
||
|
*
|
||
|
* !?!?! 2DO: optimization: iterate max(cache_size and \asize) / linesize
|
||
|
*/
|
||
|
|
||
|
.macro cache_hit_region cainst, linesize_log2, addr, asize, askew
|
||
|
|
||
|
// Make \asize the number of iterations:
|
||
|
extui \askew, \addr, 0, \linesize_log2 // get unalignment amount of \addr
|
||
|
add \asize, \asize, \askew // ... and add it to \asize
|
||
|
addi \asize, \asize, (1 << \linesize_log2) - 1 // round up!
|
||
|
srli \asize, \asize, \linesize_log2
|
||
|
|
||
|
// Iterate over region:
|
||
|
floopnez \asize, cacheh\@
|
||
|
\cainst \addr, 0
|
||
|
addi \addr, \addr, (1 << \linesize_log2) // move to next line
|
||
|
floopend \asize, cacheh\@
|
||
|
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*************************** INSTRUCTION CACHE ***************************/
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Reset/initialize the instruction cache by simply invalidating it:
|
||
|
* (need to unlock first also, if cache locking implemented):
|
||
|
*
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro icache_reset aa, ab
|
||
|
icache_unlock_all \aa, \ab
|
||
|
icache_invalidate_all \aa, \ab
|
||
|
.endm
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Synchronize after an instruction cache operation,
|
||
|
* to be sure everything is in sync with memory as to be
|
||
|
* expected following any previous instruction cache control operations.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar an address register (temporary) (currently unused, but may be used in future)
|
||
|
*/
|
||
|
.macro icache_sync ar
|
||
|
#if XCHAL_ICACHE_SIZE > 0
|
||
|
isync
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Invalidate a single line of the instruction cache.
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to invalidate
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset (optional) offset to add to \ar to compute effective address to invalidate
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro icache_invalidate_line ar, offset
|
||
|
#if XCHAL_ICACHE_SIZE > 0
|
||
|
ihi \ar, \offset // invalidate icache line
|
||
|
/*
|
||
|
* NOTE: in some version of the silicon [!!!SHOULD HAVE BEEN DOCUMENTED!!!]
|
||
|
* 'ihi' doesn't work, so it had been replaced with 'iii'
|
||
|
* (which would just invalidate more than it should,
|
||
|
* which should be okay other than the performance hit
|
||
|
* because cache locking did not exist in that version,
|
||
|
* unless user somehow relies on something being cached).
|
||
|
* [WHAT VERSION IS IT!!?!?
|
||
|
* IS THERE ANY WAY TO TEST FOR THAT HERE, TO OUTPUT 'III' ONLY IF NEEDED!?!?].
|
||
|
*
|
||
|
* iii \ar, \offset
|
||
|
*/
|
||
|
icache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Invalidate instruction cache entries that cache a specified portion of memory.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro icache_invalidate_region astart, asize, ac
|
||
|
#if XCHAL_ICACHE_SIZE > 0
|
||
|
// Instruction cache region invalidation:
|
||
|
cache_hit_region ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
icache_sync \ac
|
||
|
// End of instruction cache region invalidation
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Invalidate entire instruction cache.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro icache_invalidate_all aa, ab
|
||
|
#if XCHAL_ICACHE_SIZE > 0
|
||
|
// Instruction cache invalidation:
|
||
|
cache_index_all iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab
|
||
|
icache_sync \aa
|
||
|
// End of instruction cache invalidation
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lock (prefetch & lock) a single line of the instruction cache.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to lock
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset offset to add to \ar to compute effective address to lock
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro icache_lock_line ar, offset
|
||
|
#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
|
||
|
ipfl \ar, \offset /* prefetch and lock icache line */
|
||
|
icache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lock (prefetch & lock) a specified portion of memory into the instruction cache.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro icache_lock_region astart, asize, ac
|
||
|
#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
|
||
|
// Instruction cache region lock:
|
||
|
cache_hit_region ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
icache_sync \ac
|
||
|
// End of instruction cache region lock
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Unlock a single line of the instruction cache.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to unlock
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset offset to add to \ar to compute effective address to unlock
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro icache_unlock_line ar, offset
|
||
|
#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
|
||
|
ihu \ar, \offset /* unlock icache line */
|
||
|
icache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Unlock a specified portion of memory from the instruction cache.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro icache_unlock_region astart, asize, ac
|
||
|
#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
|
||
|
// Instruction cache region unlock:
|
||
|
cache_hit_region ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
icache_sync \ac
|
||
|
// End of instruction cache region unlock
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Unlock entire instruction cache.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro icache_unlock_all aa, ab
|
||
|
#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
|
||
|
// Instruction cache unlock:
|
||
|
cache_index_all iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab
|
||
|
icache_sync \aa
|
||
|
// End of instruction cache unlock
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*************************** DATA CACHE ***************************/
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Reset/initialize the data cache by simply invalidating it
|
||
|
* (need to unlock first also, if cache locking implemented):
|
||
|
*
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro dcache_reset aa, ab
|
||
|
dcache_unlock_all \aa, \ab
|
||
|
dcache_invalidate_all \aa, \ab
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Synchronize after a data cache operation,
|
||
|
* to be sure everything is in sync with memory as to be
|
||
|
* expected following any previous data cache control operations.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar an address register (temporary) (currently unused, but may be used in future)
|
||
|
*/
|
||
|
.macro dcache_sync ar
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
// This previous sequence errs on the conservative side (too much so); a DSYNC should be sufficient:
|
||
|
//memw // synchronize data cache changes relative to subsequent memory accesses
|
||
|
//isync // be conservative and ISYNC as well (just to be sure)
|
||
|
|
||
|
dsync
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Synchronize after a data store operation,
|
||
|
* to be sure the stored data is completely off the processor
|
||
|
* (and assuming there is no buffering outside the processor,
|
||
|
* that the data is in memory). This may be required to
|
||
|
* ensure that the processor's write buffers are emptied.
|
||
|
* A MEMW followed by a read guarantees this, by definition.
|
||
|
* We also try to make sure the read itself completes.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar an address register (temporary)
|
||
|
*/
|
||
|
.macro write_sync ar
|
||
|
memw // ensure previous memory accesses are complete prior to subsequent memory accesses
|
||
|
l32i \ar, sp, 0 // completing this read ensures any previous write has completed, because of MEMW
|
||
|
//slot
|
||
|
add \ar, \ar, \ar // use the result of the read to help ensure the read completes (in future architectures)
|
||
|
.endm
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Invalidate a single line of the data cache.
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to invalidate
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset (optional) offset to add to \ar to compute effective address to invalidate
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro dcache_invalidate_line ar, offset
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
dhi \ar, \offset
|
||
|
dcache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Invalidate data cache entries that cache a specified portion of memory.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro dcache_invalidate_region astart, asize, ac
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
// Data cache region invalidation:
|
||
|
cache_hit_region dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
dcache_sync \ac
|
||
|
// End of data cache region invalidation
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
#if 0
|
||
|
/*
|
||
|
* This is a work-around for a bug in SiChip1 (???).
|
||
|
* There should be a proper mechanism for not outputting
|
||
|
* these instructions when not needed.
|
||
|
* To enable work-around, uncomment this and replace 'dii'
|
||
|
* with 'dii_s1' everywhere, eg. in dcache_invalidate_all
|
||
|
* macro below.
|
||
|
*/
|
||
|
.macro dii_s1 ar, offset
|
||
|
dii \ar, \offset
|
||
|
or \ar, \ar, \ar
|
||
|
or \ar, \ar, \ar
|
||
|
or \ar, \ar, \ar
|
||
|
or \ar, \ar, \ar
|
||
|
.endm
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Invalidate entire data cache.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro dcache_invalidate_all aa, ab
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
// Data cache invalidation:
|
||
|
cache_index_all dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab
|
||
|
dcache_sync \aa
|
||
|
// End of data cache invalidation
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Writeback a single line of the data cache.
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to writeback
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset offset to add to \ar to compute effective address to writeback
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro dcache_writeback_line ar, offset
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
|
||
|
dhwb \ar, \offset
|
||
|
dcache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Writeback dirty data cache entries that cache a specified portion of memory.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro dcache_writeback_region astart, asize, ac
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
|
||
|
// Data cache region writeback:
|
||
|
cache_hit_region dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
dcache_sync \ac
|
||
|
// End of data cache region writeback
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Writeback entire data cache.
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro dcache_writeback_all aa, ab
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
|
||
|
// Data cache writeback:
|
||
|
cache_index_all diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
|
||
|
dcache_sync \aa
|
||
|
// End of data cache writeback
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Writeback and invalidate a single line of the data cache.
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to writeback and invalidate
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset offset to add to \ar to compute effective address to writeback and invalidate
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro dcache_writeback_inv_line ar, offset
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
dhwbi \ar, \offset /* writeback and invalidate dcache line */
|
||
|
dcache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Writeback and invalidate data cache entries that cache a specified portion of memory.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro dcache_writeback_inv_region astart, asize, ac
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
// Data cache region writeback and invalidate:
|
||
|
cache_hit_region dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
dcache_sync \ac
|
||
|
// End of data cache region writeback and invalidate
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Writeback and invalidate entire data cache.
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro dcache_writeback_inv_all aa, ab
|
||
|
#if XCHAL_DCACHE_SIZE > 0
|
||
|
// Data cache writeback and invalidate:
|
||
|
#if XCHAL_DCACHE_IS_WRITEBACK
|
||
|
cache_index_all diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
|
||
|
dcache_sync \aa
|
||
|
#else /*writeback*/
|
||
|
// Data cache does not support writeback, so just invalidate: */
|
||
|
dcache_invalidate_all \aa, \ab
|
||
|
#endif /*writeback*/
|
||
|
// End of data cache writeback and invalidate
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lock (prefetch & lock) a single line of the data cache.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to lock
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset offset to add to \ar to compute effective address to lock
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro dcache_lock_line ar, offset
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
|
||
|
dpfl \ar, \offset /* prefetch and lock dcache line */
|
||
|
dcache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lock (prefetch & lock) a specified portion of memory into the data cache.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro dcache_lock_region astart, asize, ac
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
|
||
|
// Data cache region lock:
|
||
|
cache_hit_region dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
dcache_sync \ac
|
||
|
// End of data cache region lock
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Unlock a single line of the data cache.
|
||
|
*
|
||
|
* Parameters are:
|
||
|
* ar address register that contains (virtual) address to unlock
|
||
|
* (may get clobbered in a future implementation, but not currently)
|
||
|
* offset offset to add to \ar to compute effective address to unlock
|
||
|
* (note: some number of lsbits are ignored)
|
||
|
*/
|
||
|
.macro dcache_unlock_line ar, offset
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
|
||
|
dhu \ar, \offset /* unlock dcache line */
|
||
|
dcache_sync \ar
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Unlock a specified portion of memory from the data cache.
|
||
|
* Parameters are:
|
||
|
* astart start address (register gets clobbered)
|
||
|
* asize size of the region in bytes (register gets clobbered)
|
||
|
* ac unique register used as temporary
|
||
|
*/
|
||
|
.macro dcache_unlock_region astart, asize, ac
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
|
||
|
// Data cache region unlock:
|
||
|
cache_hit_region dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
|
||
|
dcache_sync \ac
|
||
|
// End of data cache region unlock
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Unlock entire data cache.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* aa, ab unique address registers (temporaries)
|
||
|
*/
|
||
|
.macro dcache_unlock_all aa, ab
|
||
|
#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
|
||
|
// Data cache unlock:
|
||
|
cache_index_all diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
|
||
|
dcache_sync \aa
|
||
|
// End of data cache unlock
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
|
||
|
#endif /*XTENSA_CACHEASM_H*/
|
||
|
|