2006-12-10 02:18:48 -08:00
/*
* include / asm - xtensa / asmmacro . h
*
* 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 ) 2005 Tensilica Inc .
*/
# ifndef _XTENSA_ASMMACRO_H
# define _XTENSA_ASMMACRO_H
2008-11-06 06:40:46 -08:00
# include <variant/core.h>
2006-12-10 02:18:48 -08:00
/*
* Some little helpers for loops . Use zero - overhead - loops
* where applicable and if supported by the processor .
*
* __loopi ar , at , size , inc
* ar register initialized with the start address
* at scratch register used by macro
* size size immediate value
* inc increment
*
* __loops ar , as , at , inc_log2 [ , mask_log2 ] [ , cond ] [ , ncond ]
* ar register initialized with the start address
* as register initialized with the size
* at scratch register use by macro
* inc_log2 increment [ in log2 ]
* mask_log2 mask [ in log2 ]
* cond true condition ( used in loop ' cond ' )
* ncond false condition ( used in b ' ncond ' )
*
* __loop as
* restart loop . ' as ' register must not have been modified !
*
2015-09-24 23:11:53 +03:00
* __endla ar , as , incr
2006-12-10 02:18:48 -08:00
* ar start address ( modified )
2015-09-24 23:11:53 +03:00
* as scratch register used by __loops / __loopi macros or
* end address used by __loopt macro
2006-12-10 02:18:48 -08:00
* inc increment
*/
/*
* loop for given size as immediate
*/
. macro __loopi ar , at , size , incr
# if XCHAL_HAVE_LOOPS
movi \ at , ( ( \ size + \ incr - 1 ) / ( \ incr ) )
loop \ at , 99f
# else
addi \ at , \ ar , \ size
98 :
# endif
. endm
/*
* loop for given size in register
*/
. macro __loops ar , as , at , incr_log2 , mask_log2 , cond , ncond
# if XCHAL_HAVE_LOOPS
. ifgt \ incr_log2 - 1
addi \ at , \ as , ( 1 < < \ incr_log2 ) - 1
. ifnc \ mask_log2 ,
extui \ at , \ at , \ incr_log2 , \ mask_log2
. else
srli \ at , \ at , \ incr_log2
. endif
. endif
loop \ cond \ at , 99f
# else
. ifnc \ mask_log2 ,
extui \ at , \ as , \ incr_log2 , \ mask_log2
. else
. ifnc \ ncond ,
srli \ at , \ as , \ incr_log2
. endif
. endif
. ifnc \ ncond ,
b \ ncond \ at , 99f
. endif
. ifnc \ mask_log2 ,
slli \ at , \ at , \ incr_log2
add \ at , \ ar , \ at
. else
add \ at , \ ar , \ as
. endif
# endif
98 :
. endm
/*
2015-09-24 23:11:53 +03:00
* loop from ar to as
2006-12-10 02:18:48 -08:00
*/
. macro __loopt ar , as , at , incr_log2
# if XCHAL_HAVE_LOOPS
sub \ at , \ as , \ ar
. ifgt \ incr_log2 - 1
addi \ at , \ at , ( 1 < < \ incr_log2 ) - 1
srli \ at , \ at , \ incr_log2
. endif
loop \ at , 99f
# else
98 :
# endif
. endm
/*
* restart loop . registers must be unchanged
*/
. macro __loop as
# if XCHAL_HAVE_LOOPS
loop \ as , 99f
# else
98 :
# endif
. endm
/*
* end of loop with no increment of the address .
*/
. macro __endl ar , as
# if !XCHAL_HAVE_LOOPS
bltu \ ar , \ as , 98 b
# endif
99 :
. endm
/*
* end of loop with increment of the address .
*/
. macro __endla ar , as , incr
addi \ ar , \ ar , \ incr
__endl \ ar \ as
. endm
2017-12-09 21:18:47 -08:00
/* Load or store instructions that may cause exceptions use the EX macro. */
# define EX(handler) \
. section __ex_table , " a " ; \
. word 97f , handler ; \
. previous \
97 :
2006-12-10 02:18:48 -08:00
2017-12-09 21:21:35 -08:00
/*
* Extract unaligned word that is split between two registers w0 and w1
* into r regardless of machine endianness . SAR must be loaded with the
* starting bit of the word ( see __ssa8 ) .
*/
. macro __src_b r , w0 , w1
# ifdef __XTENSA_EB__
src \ r , \ w0 , \ w1
# else
src \ r , \ w1 , \ w0
# endif
. endm
/*
* Load 2 lowest address bits of r into SAR for __src_b to extract unaligned
* word starting at r from two registers loaded from consecutive aligned
* addresses covering r regardless of machine endianness .
*
* r 0 1 2 3
* LE SAR 0 8 16 24
* BE SAR 32 24 16 8
*/
. macro __ssa8 r
# ifdef __XTENSA_EB__
ssa8b \ r
# else
ssa8l \ r
# endif
. endm
2006-12-10 02:18:48 -08:00
# endif /* _XTENSA_ASMMACRO_H */