1 /*
2  * include/asm-xtensa/asmmacro.h
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 2005 Tensilica Inc.
9  */
10 
11 #ifndef _XTENSA_ASMMACRO_H
12 #define _XTENSA_ASMMACRO_H
13 
14 #include <asm-generic/export.h>
15 #include <asm/core.h>
16 
17 /*
18  * Some little helpers for loops. Use zero-overhead-loops
19  * where applicable and if supported by the processor.
20  *
21  * __loopi ar, at, size, inc
22  *         ar	register initialized with the start address
23  *	   at	scratch register used by macro
24  *	   size	size immediate value
25  *	   inc	increment
26  *
27  * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
28  *	   ar	register initialized with the start address
29  *	   as	register initialized with the size
30  *	   at	scratch register use by macro
31  *	   inc_log2	increment [in log2]
32  *	   mask_log2	mask [in log2]
33  *	   cond		true condition (used in loop'cond')
34  *	   ncond	false condition (used in b'ncond')
35  *
36  * __loop  as
37  *	   restart loop. 'as' register must not have been modified!
38  *
39  * __endla ar, as, incr
40  *	   ar	start address (modified)
41  *	   as	scratch register used by __loops/__loopi macros or
42  *		end address used by __loopt macro
43  *	   inc	increment
44  */
45 
46 /*
47  * loop for given size as immediate
48  */
49 
50 	.macro	__loopi ar, at, size, incr
51 
52 #if XCHAL_HAVE_LOOPS
53 		movi	\at, ((\size + \incr - 1) / (\incr))
54 		loop	\at, 99f
55 #else
56 		addi	\at, \ar, \size
57 		98:
58 #endif
59 
60 	.endm
61 
62 /*
63  * loop for given size in register
64  */
65 
66 	.macro	__loops	ar, as, at, incr_log2, mask_log2, cond, ncond
67 
68 #if XCHAL_HAVE_LOOPS
69 		.ifgt \incr_log2 - 1
70 			addi	\at, \as, (1 << \incr_log2) - 1
71 			.ifnc \mask_log2,
72 				extui	\at, \at, \incr_log2, \mask_log2
73 			.else
74 				srli	\at, \at, \incr_log2
75 			.endif
76 		.endif
77 		loop\cond	\at, 99f
78 #else
79 		.ifnc \mask_log2,
80 			extui	\at, \as, \incr_log2, \mask_log2
81 		.else
82 			.ifnc \ncond,
83 				srli	\at, \as, \incr_log2
84 			.endif
85 		.endif
86 		.ifnc \ncond,
87 			b\ncond	\at, 99f
88 
89 		.endif
90 		.ifnc \mask_log2,
91 			slli	\at, \at, \incr_log2
92 			add	\at, \ar, \at
93 		.else
94 			add	\at, \ar, \as
95 		.endif
96 #endif
97 		98:
98 
99 	.endm
100 
101 /*
102  * loop from ar to as
103  */
104 
105 	.macro	__loopt	ar, as, at, incr_log2
106 
107 #if XCHAL_HAVE_LOOPS
108 		sub	\at, \as, \ar
109 		.ifgt	\incr_log2 - 1
110 			addi	\at, \at, (1 << \incr_log2) - 1
111 			srli	\at, \at, \incr_log2
112 		.endif
113 		loop	\at, 99f
114 #else
115 		98:
116 #endif
117 
118 	.endm
119 
120 /*
121  * restart loop. registers must be unchanged
122  */
123 
124 	.macro	__loop	as
125 
126 #if XCHAL_HAVE_LOOPS
127 		loop	\as, 99f
128 #else
129 		98:
130 #endif
131 
132 	.endm
133 
134 /*
135  * end of loop with no increment of the address.
136  */
137 
138 	.macro	__endl	ar, as
139 #if !XCHAL_HAVE_LOOPS
140 		bltu	\ar, \as, 98b
141 #endif
142 		99:
143 	.endm
144 
145 /*
146  * end of loop with increment of the address.
147  */
148 
149 	.macro	__endla	ar, as, incr
150 		addi	\ar, \ar, \incr
151 		__endl	\ar \as
152 	.endm
153 
154 /* Load or store instructions that may cause exceptions use the EX macro. */
155 
156 #define EX(handler)				\
157 	.section __ex_table, "a";		\
158 	.word	97f, handler;			\
159 	.previous				\
160 97:
161 
162 
163 /*
164  * Extract unaligned word that is split between two registers w0 and w1
165  * into r regardless of machine endianness. SAR must be loaded with the
166  * starting bit of the word (see __ssa8).
167  */
168 
169 	.macro __src_b	r, w0, w1
170 #ifdef __XTENSA_EB__
171 		src	\r, \w0, \w1
172 #else
173 		src	\r, \w1, \w0
174 #endif
175 	.endm
176 
177 /*
178  * Load 2 lowest address bits of r into SAR for __src_b to extract unaligned
179  * word starting at r from two registers loaded from consecutive aligned
180  * addresses covering r regardless of machine endianness.
181  *
182  *      r   0   1   2   3
183  * LE SAR   0   8  16  24
184  * BE SAR  32  24  16   8
185  */
186 
187 	.macro __ssa8	r
188 #ifdef __XTENSA_EB__
189 		ssa8b	\r
190 #else
191 		ssa8l	\r
192 #endif
193 	.endm
194 
195 	.macro	do_nsau cnt, val, tmp, a
196 #if XCHAL_HAVE_NSA
197 	nsau	\cnt, \val
198 #else
199 	mov	\a, \val
200 	movi	\cnt, 0
201 	extui	\tmp, \a, 16, 16
202 	bnez	\tmp, 0f
203 	movi	\cnt, 16
204 	slli	\a, \a, 16
205 0:
206 	extui	\tmp, \a, 24, 8
207 	bnez	\tmp, 1f
208 	addi	\cnt, \cnt, 8
209 	slli	\a, \a, 8
210 1:
211 	movi	\tmp, __nsau_data
212 	extui	\a, \a, 24, 8
213 	add	\tmp, \tmp, \a
214 	l8ui	\tmp, \tmp, 0
215 	add	\cnt, \cnt, \tmp
216 #endif /* !XCHAL_HAVE_NSA */
217 	.endm
218 
219 	.macro	do_abs dst, src, tmp
220 #if XCHAL_HAVE_ABS
221 	abs	\dst, \src
222 #else
223 	neg	\tmp, \src
224 	movgez	\tmp, \src, \src
225 	mov	\dst, \tmp
226 #endif
227 	.endm
228 
229 #if defined(__XTENSA_WINDOWED_ABI__)
230 
231 /* Assembly instructions for windowed kernel ABI. */
232 #define KABI_W
233 /* Assembly instructions for call0 kernel ABI (will be ignored). */
234 #define KABI_C0 #
235 
236 #define XTENSA_FRAME_SIZE_RESERVE	16
237 #define XTENSA_SPILL_STACK_RESERVE	32
238 
239 #define abi_entry(frame_size) \
240 	entry sp, (XTENSA_FRAME_SIZE_RESERVE + \
241 		   (((frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \
242 		    -XTENSA_STACK_ALIGNMENT))
243 #define abi_entry_default abi_entry(0)
244 
245 #define abi_ret(frame_size) retw
246 #define abi_ret_default retw
247 
248 	/* direct call */
249 #define abi_call call4
250 	/* indirect call */
251 #define abi_callx callx4
252 	/* outgoing call argument registers */
253 #define abi_arg0 a6
254 #define abi_arg1 a7
255 #define abi_arg2 a8
256 #define abi_arg3 a9
257 #define abi_arg4 a10
258 #define abi_arg5 a11
259 	/* return value */
260 #define abi_rv a6
261 	/* registers preserved across call */
262 #define abi_saved0 a2
263 #define abi_saved1 a3
264 
265 	/* none of the above */
266 #define abi_tmp0 a4
267 #define abi_tmp1 a5
268 
269 #elif defined(__XTENSA_CALL0_ABI__)
270 
271 /* Assembly instructions for windowed kernel ABI (will be ignored). */
272 #define KABI_W #
273 /* Assembly instructions for call0 kernel ABI. */
274 #define KABI_C0
275 
276 #define XTENSA_SPILL_STACK_RESERVE	0
277 
278 #define abi_entry(frame_size) __abi_entry (frame_size)
279 
280 	.macro	__abi_entry frame_size
281 	.ifgt \frame_size
282 	addi sp, sp, -(((\frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \
283 		       -XTENSA_STACK_ALIGNMENT)
284 	.endif
285 	.endm
286 
287 #define abi_entry_default
288 
289 #define abi_ret(frame_size) __abi_ret (frame_size)
290 
291 	.macro	__abi_ret frame_size
292 	.ifgt \frame_size
293 	addi sp, sp, (((\frame_size) + XTENSA_STACK_ALIGNMENT - 1) & \
294 		      -XTENSA_STACK_ALIGNMENT)
295 	.endif
296 	ret
297 	.endm
298 
299 #define abi_ret_default ret
300 
301 	/* direct call */
302 #define abi_call call0
303 	/* indirect call */
304 #define abi_callx callx0
305 	/* outgoing call argument registers */
306 #define abi_arg0 a2
307 #define abi_arg1 a3
308 #define abi_arg2 a4
309 #define abi_arg3 a5
310 #define abi_arg4 a6
311 #define abi_arg5 a7
312 	/* return value */
313 #define abi_rv a2
314 	/* registers preserved across call */
315 #define abi_saved0 a12
316 #define abi_saved1 a13
317 
318 	/* none of the above */
319 #define abi_tmp0 a8
320 #define abi_tmp1 a9
321 
322 #else
323 #error Unsupported Xtensa ABI
324 #endif
325 
326 #if defined(USER_SUPPORT_WINDOWED)
327 /* Assembly instructions for windowed user ABI. */
328 #define UABI_W
329 /* Assembly instructions for call0 user ABI (will be ignored). */
330 #define UABI_C0 #
331 #else
332 /* Assembly instructions for windowed user ABI (will be ignored). */
333 #define UABI_W #
334 /* Assembly instructions for call0 user ABI. */
335 #define UABI_C0
336 #endif
337 
338 #define __XTENSA_HANDLER	.section ".exception.text", "ax"
339 
340 #endif /* _XTENSA_ASMMACRO_H */
341