18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * include/asm-xtensa/asmmacro.h
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
58c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
68c2ecf20Sopenharmony_ci * for more details.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2005 Tensilica Inc.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifndef _XTENSA_ASMMACRO_H
128c2ecf20Sopenharmony_ci#define _XTENSA_ASMMACRO_H
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <asm/core.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/*
178c2ecf20Sopenharmony_ci * Some little helpers for loops. Use zero-overhead-loops
188c2ecf20Sopenharmony_ci * where applicable and if supported by the processor.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * __loopi ar, at, size, inc
218c2ecf20Sopenharmony_ci *         ar	register initialized with the start address
228c2ecf20Sopenharmony_ci *	   at	scratch register used by macro
238c2ecf20Sopenharmony_ci *	   size	size immediate value
248c2ecf20Sopenharmony_ci *	   inc	increment
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
278c2ecf20Sopenharmony_ci *	   ar	register initialized with the start address
288c2ecf20Sopenharmony_ci *	   as	register initialized with the size
298c2ecf20Sopenharmony_ci *	   at	scratch register use by macro
308c2ecf20Sopenharmony_ci *	   inc_log2	increment [in log2]
318c2ecf20Sopenharmony_ci *	   mask_log2	mask [in log2]
328c2ecf20Sopenharmony_ci *	   cond		true condition (used in loop'cond')
338c2ecf20Sopenharmony_ci *	   ncond	false condition (used in b'ncond')
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * __loop  as
368c2ecf20Sopenharmony_ci *	   restart loop. 'as' register must not have been modified!
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * __endla ar, as, incr
398c2ecf20Sopenharmony_ci *	   ar	start address (modified)
408c2ecf20Sopenharmony_ci *	   as	scratch register used by __loops/__loopi macros or
418c2ecf20Sopenharmony_ci *		end address used by __loopt macro
428c2ecf20Sopenharmony_ci *	   inc	increment
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/*
468c2ecf20Sopenharmony_ci * loop for given size as immediate
478c2ecf20Sopenharmony_ci */
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	.macro	__loopi ar, at, size, incr
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#if XCHAL_HAVE_LOOPS
528c2ecf20Sopenharmony_ci		movi	\at, ((\size + \incr - 1) / (\incr))
538c2ecf20Sopenharmony_ci		loop	\at, 99f
548c2ecf20Sopenharmony_ci#else
558c2ecf20Sopenharmony_ci		addi	\at, \ar, \size
568c2ecf20Sopenharmony_ci		98:
578c2ecf20Sopenharmony_ci#endif
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	.endm
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * loop for given size in register
638c2ecf20Sopenharmony_ci */
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	.macro	__loops	ar, as, at, incr_log2, mask_log2, cond, ncond
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#if XCHAL_HAVE_LOOPS
688c2ecf20Sopenharmony_ci		.ifgt \incr_log2 - 1
698c2ecf20Sopenharmony_ci			addi	\at, \as, (1 << \incr_log2) - 1
708c2ecf20Sopenharmony_ci			.ifnc \mask_log2,
718c2ecf20Sopenharmony_ci				extui	\at, \at, \incr_log2, \mask_log2
728c2ecf20Sopenharmony_ci			.else
738c2ecf20Sopenharmony_ci				srli	\at, \at, \incr_log2
748c2ecf20Sopenharmony_ci			.endif
758c2ecf20Sopenharmony_ci		.endif
768c2ecf20Sopenharmony_ci		loop\cond	\at, 99f
778c2ecf20Sopenharmony_ci#else
788c2ecf20Sopenharmony_ci		.ifnc \mask_log2,
798c2ecf20Sopenharmony_ci			extui	\at, \as, \incr_log2, \mask_log2
808c2ecf20Sopenharmony_ci		.else
818c2ecf20Sopenharmony_ci			.ifnc \ncond,
828c2ecf20Sopenharmony_ci				srli	\at, \as, \incr_log2
838c2ecf20Sopenharmony_ci			.endif
848c2ecf20Sopenharmony_ci		.endif
858c2ecf20Sopenharmony_ci		.ifnc \ncond,
868c2ecf20Sopenharmony_ci			b\ncond	\at, 99f
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		.endif
898c2ecf20Sopenharmony_ci		.ifnc \mask_log2,
908c2ecf20Sopenharmony_ci			slli	\at, \at, \incr_log2
918c2ecf20Sopenharmony_ci			add	\at, \ar, \at
928c2ecf20Sopenharmony_ci		.else
938c2ecf20Sopenharmony_ci			add	\at, \ar, \as
948c2ecf20Sopenharmony_ci		.endif
958c2ecf20Sopenharmony_ci#endif
968c2ecf20Sopenharmony_ci		98:
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	.endm
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/*
1018c2ecf20Sopenharmony_ci * loop from ar to as
1028c2ecf20Sopenharmony_ci */
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	.macro	__loopt	ar, as, at, incr_log2
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci#if XCHAL_HAVE_LOOPS
1078c2ecf20Sopenharmony_ci		sub	\at, \as, \ar
1088c2ecf20Sopenharmony_ci		.ifgt	\incr_log2 - 1
1098c2ecf20Sopenharmony_ci			addi	\at, \at, (1 << \incr_log2) - 1
1108c2ecf20Sopenharmony_ci			srli	\at, \at, \incr_log2
1118c2ecf20Sopenharmony_ci		.endif
1128c2ecf20Sopenharmony_ci		loop	\at, 99f
1138c2ecf20Sopenharmony_ci#else
1148c2ecf20Sopenharmony_ci		98:
1158c2ecf20Sopenharmony_ci#endif
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	.endm
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/*
1208c2ecf20Sopenharmony_ci * restart loop. registers must be unchanged
1218c2ecf20Sopenharmony_ci */
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	.macro	__loop	as
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#if XCHAL_HAVE_LOOPS
1268c2ecf20Sopenharmony_ci		loop	\as, 99f
1278c2ecf20Sopenharmony_ci#else
1288c2ecf20Sopenharmony_ci		98:
1298c2ecf20Sopenharmony_ci#endif
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	.endm
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/*
1348c2ecf20Sopenharmony_ci * end of loop with no increment of the address.
1358c2ecf20Sopenharmony_ci */
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	.macro	__endl	ar, as
1388c2ecf20Sopenharmony_ci#if !XCHAL_HAVE_LOOPS
1398c2ecf20Sopenharmony_ci		bltu	\ar, \as, 98b
1408c2ecf20Sopenharmony_ci#endif
1418c2ecf20Sopenharmony_ci		99:
1428c2ecf20Sopenharmony_ci	.endm
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/*
1458c2ecf20Sopenharmony_ci * end of loop with increment of the address.
1468c2ecf20Sopenharmony_ci */
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	.macro	__endla	ar, as, incr
1498c2ecf20Sopenharmony_ci		addi	\ar, \ar, \incr
1508c2ecf20Sopenharmony_ci		__endl	\ar \as
1518c2ecf20Sopenharmony_ci	.endm
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/* Load or store instructions that may cause exceptions use the EX macro. */
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci#define EX(handler)				\
1568c2ecf20Sopenharmony_ci	.section __ex_table, "a";		\
1578c2ecf20Sopenharmony_ci	.word	97f, handler;			\
1588c2ecf20Sopenharmony_ci	.previous				\
1598c2ecf20Sopenharmony_ci97:
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/*
1638c2ecf20Sopenharmony_ci * Extract unaligned word that is split between two registers w0 and w1
1648c2ecf20Sopenharmony_ci * into r regardless of machine endianness. SAR must be loaded with the
1658c2ecf20Sopenharmony_ci * starting bit of the word (see __ssa8).
1668c2ecf20Sopenharmony_ci */
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	.macro __src_b	r, w0, w1
1698c2ecf20Sopenharmony_ci#ifdef __XTENSA_EB__
1708c2ecf20Sopenharmony_ci		src	\r, \w0, \w1
1718c2ecf20Sopenharmony_ci#else
1728c2ecf20Sopenharmony_ci		src	\r, \w1, \w0
1738c2ecf20Sopenharmony_ci#endif
1748c2ecf20Sopenharmony_ci	.endm
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/*
1778c2ecf20Sopenharmony_ci * Load 2 lowest address bits of r into SAR for __src_b to extract unaligned
1788c2ecf20Sopenharmony_ci * word starting at r from two registers loaded from consecutive aligned
1798c2ecf20Sopenharmony_ci * addresses covering r regardless of machine endianness.
1808c2ecf20Sopenharmony_ci *
1818c2ecf20Sopenharmony_ci *      r   0   1   2   3
1828c2ecf20Sopenharmony_ci * LE SAR   0   8  16  24
1838c2ecf20Sopenharmony_ci * BE SAR  32  24  16   8
1848c2ecf20Sopenharmony_ci */
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	.macro __ssa8	r
1878c2ecf20Sopenharmony_ci#ifdef __XTENSA_EB__
1888c2ecf20Sopenharmony_ci		ssa8b	\r
1898c2ecf20Sopenharmony_ci#else
1908c2ecf20Sopenharmony_ci		ssa8l	\r
1918c2ecf20Sopenharmony_ci#endif
1928c2ecf20Sopenharmony_ci	.endm
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci#define XTENSA_STACK_ALIGNMENT		16
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#if defined(__XTENSA_WINDOWED_ABI__)
1978c2ecf20Sopenharmony_ci#define XTENSA_FRAME_SIZE_RESERVE	16
1988c2ecf20Sopenharmony_ci#define XTENSA_SPILL_STACK_RESERVE	32
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci#define abi_entry(frame_size) \
2018c2ecf20Sopenharmony_ci	entry sp, (XTENSA_FRAME_SIZE_RESERVE + \
2028c2ecf20Sopenharmony_ci		   (((frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \
2038c2ecf20Sopenharmony_ci		    -XTENSA_STACK_ALIGNMENT))
2048c2ecf20Sopenharmony_ci#define abi_entry_default abi_entry(0)
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci#define abi_ret(frame_size) retw
2078c2ecf20Sopenharmony_ci#define abi_ret_default retw
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci#elif defined(__XTENSA_CALL0_ABI__)
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci#define XTENSA_SPILL_STACK_RESERVE	0
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci#define abi_entry(frame_size) __abi_entry (frame_size)
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	.macro	__abi_entry frame_size
2168c2ecf20Sopenharmony_ci	.ifgt \frame_size
2178c2ecf20Sopenharmony_ci	addi sp, sp, -(((\frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \
2188c2ecf20Sopenharmony_ci		       -XTENSA_STACK_ALIGNMENT)
2198c2ecf20Sopenharmony_ci	.endif
2208c2ecf20Sopenharmony_ci	.endm
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci#define abi_entry_default
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci#define abi_ret(frame_size) __abi_ret (frame_size)
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	.macro	__abi_ret frame_size
2278c2ecf20Sopenharmony_ci	.ifgt \frame_size
2288c2ecf20Sopenharmony_ci	addi sp, sp, (((\frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \
2298c2ecf20Sopenharmony_ci		      -XTENSA_STACK_ALIGNMENT)
2308c2ecf20Sopenharmony_ci	.endif
2318c2ecf20Sopenharmony_ci	ret
2328c2ecf20Sopenharmony_ci	.endm
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci#define abi_ret_default ret
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci#else
2378c2ecf20Sopenharmony_ci#error Unsupported Xtensa ABI
2388c2ecf20Sopenharmony_ci#endif
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci#define __XTENSA_HANDLER	.section ".exception.text", "ax"
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci#endif /* _XTENSA_ASMMACRO_H */
243