/* * 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 #include /* * 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! * * __endla ar, as, incr * ar start address (modified) * as scratch register used by __loops/__loopi macros or * end address used by __loopt macro * 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 /* * loop from ar to as */ .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, 98b #endif 99: .endm /* * end of loop with increment of the address. */ .macro __endla ar, as, incr addi \ar, \ar, \incr __endl \ar \as .endm /* Load or store instructions that may cause exceptions use the EX macro. */ #define EX(handler) \ .section __ex_table, "a"; \ .word 97f, handler; \ .previous \ 97: /* * 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 .macro do_nsau cnt, val, tmp, a #if XCHAL_HAVE_NSA nsau \cnt, \val #else mov \a, \val movi \cnt, 0 extui \tmp, \a, 16, 16 bnez \tmp, 0f movi \cnt, 16 slli \a, \a, 16 0: extui \tmp, \a, 24, 8 bnez \tmp, 1f addi \cnt, \cnt, 8 slli \a, \a, 8 1: movi \tmp, __nsau_data extui \a, \a, 24, 8 add \tmp, \tmp, \a l8ui \tmp, \tmp, 0 add \cnt, \cnt, \tmp #endif /* !XCHAL_HAVE_NSA */ .endm .macro do_abs dst, src, tmp #if XCHAL_HAVE_ABS abs \dst, \src #else neg \tmp, \src movgez \tmp, \src, \src mov \dst, \tmp #endif .endm #if defined(__XTENSA_WINDOWED_ABI__) /* Assembly instructions for windowed kernel ABI. */ #define KABI_W /* Assembly instructions for call0 kernel ABI (will be ignored). */ #define KABI_C0 # #define XTENSA_FRAME_SIZE_RESERVE 16 #define XTENSA_SPILL_STACK_RESERVE 32 #define abi_entry(frame_size) \ entry sp, (XTENSA_FRAME_SIZE_RESERVE + \ (((frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \ -XTENSA_STACK_ALIGNMENT)) #define abi_entry_default abi_entry(0) #define abi_ret(frame_size) retw #define abi_ret_default retw /* direct call */ #define abi_call call4 /* indirect call */ #define abi_callx callx4 /* outgoing call argument registers */ #define abi_arg0 a6 #define abi_arg1 a7 #define abi_arg2 a8 #define abi_arg3 a9 #define abi_arg4 a10 #define abi_arg5 a11 /* return value */ #define abi_rv a6 /* registers preserved across call */ #define abi_saved0 a2 #define abi_saved1 a3 /* none of the above */ #define abi_tmp0 a4 #define abi_tmp1 a5 #elif defined(__XTENSA_CALL0_ABI__) /* Assembly instructions for windowed kernel ABI (will be ignored). */ #define KABI_W # /* Assembly instructions for call0 kernel ABI. */ #define KABI_C0 #define XTENSA_SPILL_STACK_RESERVE 0 #define abi_entry(frame_size) __abi_entry (frame_size) .macro __abi_entry frame_size .ifgt \frame_size addi sp, sp, -(((\frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \ -XTENSA_STACK_ALIGNMENT) .endif .endm #define abi_entry_default #define abi_ret(frame_size) __abi_ret (frame_size) .macro __abi_ret frame_size .ifgt \frame_size addi sp, sp, (((\frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \ -XTENSA_STACK_ALIGNMENT) .endif ret .endm #define abi_ret_default ret /* direct call */ #define abi_call call0 /* indirect call */ #define abi_callx callx0 /* outgoing call argument registers */ #define abi_arg0 a2 #define abi_arg1 a3 #define abi_arg2 a4 #define abi_arg3 a5 #define abi_arg4 a6 #define abi_arg5 a7 /* return value */ #define abi_rv a2 /* registers preserved across call */ #define abi_saved0 a12 #define abi_saved1 a13 /* none of the above */ #define abi_tmp0 a8 #define abi_tmp1 a9 #else #error Unsupported Xtensa ABI #endif #if defined(USER_SUPPORT_WINDOWED) /* Assembly instructions for windowed user ABI. */ #define UABI_W /* Assembly instructions for call0 user ABI (will be ignored). */ #define UABI_C0 # #else /* Assembly instructions for windowed user ABI (will be ignored). */ #define UABI_W # /* Assembly instructions for call0 user ABI. */ #define UABI_C0 #endif #define __XTENSA_HANDLER .section ".exception.text", "ax" #endif /* _XTENSA_ASMMACRO_H */