Files
Arquivotheca.AIX-4.1.3/bos/kernel/lib/libsysp/POWER/cacheinval.s
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

151 lines
4.8 KiB
ArmAsm

# @(#)74 1.3 src/bos/kernel/lib/libsysp/POWER/cacheinval.s, libsysp, bos411, 9428A410j 3/23/94 11:10:46
#**********************************************************************
# COMPONENT_NAME: (LIBSYSP)
#
# FUNCTIONS: cache_inval
#
# ORIGINS: 27
#
# IBM CONFIDENTIAL -- (IBM Confidential Restricted when
# combined with the aggregated modules for this product)
# SOURCE MATERIALS
# (C) COPYRIGHT International Business Machines Corp. 1989,1993
# All Rights Reserved
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
# Libsysp platform specific modules
#**********************************************************************
.file "cacheinval.s"
.machine "any"
#**********************************************************************
#
# NAME: cache_inval
#
# FUNCTION: flush cache lines for an address range
#
# cache_inval(eaddr,nbytes) rc = none
#
# INPUT STATE:
# r3 = eaddr
# r4 = nbytes
#
# OUTPUT STATE:
# The designated lines in the cache have been invalidated.
#
# EXECUTION ENVIRONMENT:
# Supervisor state : Yes
#
# NOTES:
# This routine is a NOOP for Power PC machine.
# The input effective address may have any alignment in a page, and
# the address range may be any within the current address space.
# The kernel will crash if the address range is not covered by the current
# address space.
#
# cache_inval() will first flush cache line of either end of the range
# if it is not cache aligned.
#
# cache_inval() is to be used by device drivers to clean up DATA CACHE
# for a buffer area before starting a DMA-read.
# To optimize its performance, data cache line size (instead of
# min cache line size) is used in the computation.
# This routine WILL NOT WORK if drivers want to DMA-read INSTRUCTIONS
# into its buffer.
#
#**********************************************************************
.set DCLSZ,0xd # data cache line size selector
S_PROLOG(cache_inval)
# r5 = address of _system_configuration structure
LTOC(r5,_system_configuration,data)
# check parameters
cmpi cr0,r4,0 # see if nbytes is le 0
l r9,scfg_arch(r5) # architecture field
bler # return if nbytes <= 0
cmpi cr1,r9,POWER_RS # check the architecture
a r8,r4,r3
bner cr1 # return if not POWER_RS
clcs r6,DCLSZ # r6 = the data cache line size,
ai r8,r8,-1 # r8 = eaddr of the last byte
ai r7,r6,-1 # r7 = mask of log2(clsize) length
# --this assumes cache line sizes are
# a power of two.
# num_cache_lines =
# (offset_into_cache_line + nbytes + cache_line - 1) / cache_line_size
cntlz r12,r6
and. r11,r7,r3 # r11 = offset of starting addr in cache line
sfi r12,r12,31 # r12 = log2(data cache line size)
a r11,r11,r4
and r9,r8,r7 # r9 = offset of last byte in the last line
a r4,r11,r7 # r4 = (offset + nbytes + cache line size - 1)
cmp cr1,r9,r7 # check if entire last line is covered
sr r10,r4,r12 # r10 = covered line count
mr r11,r10 # initialize r11 = # cache line
# check if the starting address is aligned on a cache line boundary
# if it is not then flush the cache line
beq cifulline1 # branch if starting address aligned
ai. r11,r11,-1 # r11 = # cache line
clf 0,r3 # flush the cache line
beq dsync
# check if the last cache line is fully covered by the range
# if it is not then flush the last cache line
cifulline1:
sf r3,r6,r3 # substract line size to start loop
beq cr1,cifulline2 # branch if the last line is fully covered
ai. r11,r11,-1 # r11 = # whole line
clf 0,r8 # flush the last line
beq dsync
# invalidate the remaining lines
cifulline2:
sri r8,r10,2 # r8 = bigloop count
cmp cr1,r10,r11 # check if clf ever executed
andil. r9,r10,0x3 # r9 = # lines to flush in remainloop
cmpi cr6,r8,0 # check if big loop count is 0
beq cr1,noclf
dcs # wait for memory to be stored if clf executed
noclf:
beq bigloop # branch if nothing left for remainloop
mtctr r9 # setup loop count
remainloop:
cli r3,r6 # cache line invalidate
bdn remainloop # dec ctr and branch if non-zero
bigloop:
beq cr6,isync
mtctr r8 # setup loop count
bigloop1:
cli r3,r6
cli r3,r6
cli r3,r6
cli r3,r6
bdn bigloop1 # dec ctr and branch if non-zero
isync: ics # wait for cli to be completed and
br # refetch any fetched instructions
dsync: dcs # wait for memory to be stored if only
# execute clf's
S_EPILOG
.toc
TOCE(_system_configuration,data)
include(INCLML/systemcfg.m4)