GNU Linux-libre 4.19.281-gnu1
[releases.git] / arch / xtensa / include / asm / asmmacro.h
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 <variant/core.h>
15
16 /*
17  * Some little helpers for loops. Use zero-overhead-loops
18  * where applicable and if supported by the processor.
19  *
20  * __loopi ar, at, size, inc
21  *         ar   register initialized with the start address
22  *         at   scratch register used by macro
23  *         size size immediate value
24  *         inc  increment
25  *
26  * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
27  *         ar   register initialized with the start address
28  *         as   register initialized with the size
29  *         at   scratch register use by macro
30  *         inc_log2     increment [in log2]
31  *         mask_log2    mask [in log2]
32  *         cond         true condition (used in loop'cond')
33  *         ncond        false condition (used in b'ncond')
34  *
35  * __loop  as
36  *         restart loop. 'as' register must not have been modified!
37  *
38  * __endla ar, as, incr
39  *         ar   start address (modified)
40  *         as   scratch register used by __loops/__loopi macros or
41  *              end address used by __loopt macro
42  *         inc  increment
43  */
44
45 /*
46  * loop for given size as immediate
47  */
48
49         .macro  __loopi ar, at, size, incr
50
51 #if XCHAL_HAVE_LOOPS
52                 movi    \at, ((\size + \incr - 1) / (\incr))
53                 loop    \at, 99f
54 #else
55                 addi    \at, \ar, \size
56                 98:
57 #endif
58
59         .endm
60
61 /*
62  * loop for given size in register
63  */
64
65         .macro  __loops ar, as, at, incr_log2, mask_log2, cond, ncond
66
67 #if XCHAL_HAVE_LOOPS
68                 .ifgt \incr_log2 - 1
69                         addi    \at, \as, (1 << \incr_log2) - 1
70                         .ifnc \mask_log2,
71                                 extui   \at, \at, \incr_log2, \mask_log2
72                         .else
73                                 srli    \at, \at, \incr_log2
74                         .endif
75                 .endif
76                 loop\cond       \at, 99f
77 #else
78                 .ifnc \mask_log2,
79                         extui   \at, \as, \incr_log2, \mask_log2
80                 .else
81                         .ifnc \ncond,
82                                 srli    \at, \as, \incr_log2
83                         .endif
84                 .endif
85                 .ifnc \ncond,
86                         b\ncond \at, 99f
87
88                 .endif
89                 .ifnc \mask_log2,
90                         slli    \at, \at, \incr_log2
91                         add     \at, \ar, \at
92                 .else
93                         add     \at, \ar, \as
94                 .endif
95 #endif
96                 98:
97
98         .endm
99
100 /*
101  * loop from ar to as
102  */
103
104         .macro  __loopt ar, as, at, incr_log2
105
106 #if XCHAL_HAVE_LOOPS
107                 sub     \at, \as, \ar
108                 .ifgt   \incr_log2 - 1
109                         addi    \at, \at, (1 << \incr_log2) - 1
110                         srli    \at, \at, \incr_log2
111                 .endif
112                 loop    \at, 99f
113 #else
114                 98:
115 #endif
116
117         .endm
118
119 /*
120  * restart loop. registers must be unchanged
121  */
122
123         .macro  __loop  as
124
125 #if XCHAL_HAVE_LOOPS
126                 loop    \as, 99f
127 #else
128                 98:
129 #endif
130
131         .endm
132
133 /*
134  * end of loop with no increment of the address.
135  */
136
137         .macro  __endl  ar, as
138 #if !XCHAL_HAVE_LOOPS
139                 bltu    \ar, \as, 98b
140 #endif
141                 99:
142         .endm
143
144 /*
145  * end of loop with increment of the address.
146  */
147
148         .macro  __endla ar, as, incr
149                 addi    \ar, \ar, \incr
150                 __endl  \ar \as
151         .endm
152
153 /* Load or store instructions that may cause exceptions use the EX macro. */
154
155 #define EX(handler)                             \
156         .section __ex_table, "a";               \
157         .word   97f, handler;                   \
158         .previous                               \
159 97:
160
161
162 /*
163  * Extract unaligned word that is split between two registers w0 and w1
164  * into r regardless of machine endianness. SAR must be loaded with the
165  * starting bit of the word (see __ssa8).
166  */
167
168         .macro __src_b  r, w0, w1
169 #ifdef __XTENSA_EB__
170                 src     \r, \w0, \w1
171 #else
172                 src     \r, \w1, \w0
173 #endif
174         .endm
175
176 /*
177  * Load 2 lowest address bits of r into SAR for __src_b to extract unaligned
178  * word starting at r from two registers loaded from consecutive aligned
179  * addresses covering r regardless of machine endianness.
180  *
181  *      r   0   1   2   3
182  * LE SAR   0   8  16  24
183  * BE SAR  32  24  16   8
184  */
185
186         .macro __ssa8   r
187 #ifdef __XTENSA_EB__
188                 ssa8b   \r
189 #else
190                 ssa8l   \r
191 #endif
192         .endm
193
194 #endif /* _XTENSA_ASMMACRO_H */