1 /*        $NetBSD: asm.h,v 1.36 2025/05/03 19:57:13 riastradh Exp $   */
2 
3 /*-
4  * Copyright (c) 2014 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matt Thomas of 3am Software Foundry.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1990 The Regents of the University of California.
34  * All rights reserved.
35  *
36  * This code is derived from software contributed to Berkeley by
37  * William Jolitz.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  * 3. Neither the name of the University nor the names of its contributors
48  *    may be used to endorse or promote products derived from this software
49  *    without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61  * SUCH DAMAGE.
62  *
63  *        from: @(#)asm.h     5.5 (Berkeley) 5/7/91
64  */
65 
66 #ifndef _ARM_ASM_H_
67 #define _ARM_ASM_H_
68 
69 #include <arm/cdefs.h>
70 #if defined(_KERNEL_OPT)
71 #include "opt_cpuoptions.h"
72 #endif
73 
74 #ifdef __thumb__
75 #define THUMB_INSN(n)         n
76 #else
77 #define THUMB_INSN(n)
78 #endif
79 
80 #define   __BIT(n)  (1 << (n))
81 #define __BITS(hi,lo)         ((~((~0)<<((hi)+1)))&((~0)<<(lo)))
82 
83 #define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
84 #define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
85 #define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask))
86 
87 #define _C_LABEL(x) x
88 #define   _ASM_LABEL(x)       x
89 
90 #ifdef __STDC__
91 # define __CONCAT(x,y)        x ## y
92 # define __STRING(x)          #x
93 #else
94 # define __CONCAT(x,y)        x/**/y
95 # define __STRING(x)          "x"
96 #endif
97 
98 #ifndef _ALIGN_TEXT
99 # define _ALIGN_TEXT .align 2
100 #endif
101 
102 #ifndef _TEXT_SECTION
103 #define _TEXT_SECTION         .text
104 #endif
105 
106 #ifdef __arm__
107 
108           .syntax             unified
109 
110 /*
111  * gas/arm uses @ as a single comment character and thus cannot be used here
112  * Instead it recognised the # instead of an @ symbols in .type directives
113  * We define a couple of macros so that assembly code will not be dependent
114  * on one or the other.
115  */
116 #define _ASM_TYPE_FUNCTION    %function
117 #define _ASM_TYPE_OBJECT      %object
118 #define _THUMB_ENTRY(x) \
119           _TEXT_SECTION; _ALIGN_TEXT; .globl x; .type x,_ASM_TYPE_FUNCTION; \
120           .thumb_func; .code 16; x:
121 #define _ARM_ENTRY(x) \
122           _TEXT_SECTION; _ALIGN_TEXT; .globl x; .type x,_ASM_TYPE_FUNCTION; \
123           .code 32; x:
124 #ifdef __thumb__
125 #define   _ENTRY(x) _THUMB_ENTRY(x)
126 #else
127 #define   _ENTRY(x) _ARM_ENTRY(x)
128 #endif
129 #define   _END(x)             .size x,.-x
130 
131 #ifdef GPROF
132 # define _PROF_PROLOGUE       \
133           mov ip, lr; bl __mcount
134 #else
135 # define _PROF_PROLOGUE
136 #endif
137 #endif
138 
139 #ifdef __aarch64__
140 #define _ASM_TYPE_FUNCTION    @function
141 #define _ASM_TYPE_OBJECT      @object
142 #define _ENTRY(x) \
143           _TEXT_SECTION; _ALIGN_TEXT; .globl x; .type x,_ASM_TYPE_FUNCTION; x:
144 #define   _END(x)             .size x,.-x
145 
146 #ifdef GPROF
147 # define _PROF_PROLOGUE       \
148           stp       x29, x30, [sp, #-16]!;        \
149           mov       fp, sp;                       \
150           bl        __mcount;                     \
151           ldp       x29, x30, [sp], #16;
152 #else
153 # define _PROF_PROLOGUE
154 #endif
155 
156 #ifdef __PIC__
157 #define GOTREF(x)             :got:x
158 #define GOTLO12(x)            :got_lo12:x
159 #else
160 #define GOTREF(x)             x
161 #define GOTLO12(x)            :lo12:x
162 #endif
163 #endif
164 
165 #ifdef ARMV85_BTI
166 #define   _BTI_PROLOGUE \
167           .byte     0x5F, 0x24, 0x03, 0xD5        /* the "bti c" instruction */
168 #else
169 #define   _BTI_PROLOGUE                 /* nothing */
170 #endif
171 
172 #define   ENTRY(y)            _ENTRY(_C_LABEL(y)); _BTI_PROLOGUE ; _PROF_PROLOGUE
173 #define   ENTRY_NP(y)                   _ENTRY(_C_LABEL(y)); _BTI_PROLOGUE
174 #define   ENTRY_NBTI(y)                 _ENTRY(_C_LABEL(y))
175 #define   END(y)                        _END(_C_LABEL(y))
176 #define   ARM_ENTRY(y)                  _ARM_ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
177 #define   ARM_ENTRY_NP(y)               _ARM_ENTRY(_C_LABEL(y))
178 #define   THUMB_ENTRY(y)                _THUMB_ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
179 #define   THUMB_ENTRY_NP(y)   _THUMB_ENTRY(_C_LABEL(y))
180 #define   ASENTRY(y)                    _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
181 #define   ASENTRY_NP(y)                 _ENTRY(_ASM_LABEL(y))
182 #define   ASEND(y)            _END(_ASM_LABEL(y))
183 #define   ARM_ASENTRY(y)                _ARM_ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
184 #define   ARM_ASENTRY_NP(y)   _ARM_ENTRY(_ASM_LABEL(y))
185 #define   THUMB_ASENTRY(y)    _THUMB_ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
186 #define   THUMB_ASENTRY_NP(y) _THUMB_ENTRY(_ASM_LABEL(y))
187 
188 #define   ASMSTR              .asciz
189 
190 #ifdef __PIC__
191 #define   REL_SYM(a, b)       ((a) - (b))
192 #define   PCREL_GET(a, label, pclabel)  \
193           ldr       a, label;           \
194 pclabel:                                \
195           add       a, a, pc
196 #ifdef __thumb__
197 #define   PCREL_SYM(a, pclabel)         REL_SYM(a, (pclabel) + 4)
198 #else
199 #define   PCREL_SYM(a, pclabel)         REL_SYM(a, (pclabel) + 8)
200 #endif
201 #define   PLT_SYM(x)          x
202 #define   GOT_SYM(x)          PIC_SYM(x, GOT)
203 #define   GOT_GET(x,got,sym)  \
204           ldr       x, sym;             \
205           ldr       x, [x, got]
206 #define   GOT_INIT(got,gotsym,pclabel) \
207           PCREL_GET(got,gotsym,pclabel)
208 #define   GOT_INITSYM(gotsym,pclabel) \
209           .align 0;           \
210           gotsym: .word PCREL_SYM(_C_LABEL(_GLOBAL_OFFSET_TABLE_), pclabel)
211 
212 #ifdef __STDC__
213 #define   PIC_SYM(x,y)        x ## ( ## y ## )
214 #else
215 #define   PIC_SYM(x,y)        x/**/(/**/y/**/)
216 #endif
217 
218 #else
219 #define   REL_SYM(a, b)       (a)
220 #define   PCREL_GET(a, label, pclabel)  \
221           ldr       a, label
222 #define   PCREL_SYM(a, pclabel)         (a)
223 #define   PLT_SYM(x)          x
224 #define   GOT_SYM(x)          x
225 #define   GOT_GET(x,got,sym)  \
226           ldr       x, sym;
227 #define   GOT_INIT(got,gotsym,pclabel)
228 #define   GOT_INITSYM(gotsym,pclabel)
229 #define   PIC_SYM(x,y)        x
230 #endif    /* __PIC__ */
231 
232 /*
233  * Annoyingly, gas on arm seems to generate _two_ NUL-terminated
234  * strings for
235  *
236  *        .asciz "foo" "bar"
237  *
238  * instead of concatenating it into a single NUL-terminated string as
239  * on other architectures.
240  *
241  * To work around this, we concatenate into a single NUL-terminated by:
242  *
243  *        .ascii "foo"
244  *        .asciz "bar"
245  */
246 #define _IDENTSTR(x)          .pushsection ".ident","MS",%progbits,1;           \
247                               x;                                                          \
248                               .popsection
249 
250 #ifdef _NETBSD_REVISIONID
251 #define   RCSID(_s)                                                             \
252           _IDENTSTR(.asciz _s);                                                           \
253           _IDENTSTR(.ascii "$"; .ascii "NetBSD: "; .ascii __FILE__;   \
254               .ascii " "; .ascii _NETBSD_REVISIONID; .asciz " $")
255 #else
256 #define   RCSID(_s) _IDENTSTR(.asciz _s)
257 #endif
258 
259 #define   WEAK_ALIAS(alias,sym)                                                           \
260           .weak alias;                                                                    \
261           alias = sym
262 
263 /*
264  * STRONG_ALIAS: create a strong alias.
265  */
266 #define STRONG_ALIAS(alias,sym)                                                           \
267           .globl alias;                                                                   \
268           alias = sym
269 
270 #ifdef __STDC__
271 #define   WARN_REFERENCES(sym,msg)                                              \
272           .pushsection .gnu.warning. ## sym;                                    \
273           .ascii msg;                                                                     \
274           .popsection
275 #else
276 #define   WARN_REFERENCES(sym,msg)                                              \
277           .pushsection .gnu.warning./**/sym;                                    \
278           .ascii msg;                                                                     \
279           .popsection
280 #endif /* __STDC__ */
281 
282 #ifdef __thumb__
283 # define XPUSH                push
284 # define XPOP                 pop
285 # define XPOPRET    pop       {pc}
286 #else
287 # define XPUSH                stmfd     sp!,
288 # define XPOP                 ldmfd     sp!,
289 # ifdef _ARM_ARCH_5
290 #  define XPOPRET   ldmfd     sp!, {pc}
291 # else
292 #  define XPOPRET   ldmfd     sp!, {lr}; mov pc, lr
293 # endif
294 #endif
295 
296 #if defined(__aarch64__)
297 # define RET                  ret
298 #elif defined (_ARM_ARCH_4T)
299 # define RET                  bx                  lr
300 # define RETr(r)    bx                  r
301 # if defined(__thumb__)
302 #  if defined(_ARM_ARCH_7)
303 #   define RETc(c)  it c; __CONCAT(bx,c)          lr
304 #  endif
305 # else
306 #  define RETc(c)   __CONCAT(bx,c)      lr
307 # endif
308 #else
309 # define RET                  mov                 pc, lr
310 # define RETr(r)    mov                 pc, r
311 # define RETc(c)    __CONCAT(mov,c)     pc, lr
312 #endif
313 
314 #ifdef _ARM_ARCH_7
315 #define KMODTRAMPOLINE(n)                         \
316 _ENTRY(__wrap_ ## n)                                        \
317           movw      ip, #:lower16:n;    \
318           movt      ip, #:upper16:n;    \
319           bx        ip
320 #elif defined(_ARM_ARCH_4T)
321 #define KMODTRAMPOLINE(n)     \
322 _ENTRY(__wrap_ ## n)                    \
323           ldr       ip, [pc]; \
324           bx        ip;                 \
325           .word     n
326 #else
327 #define KMODTRAMPOLINE(n)     \
328 _ENTRY(__wrap_ ## n)                    \
329           ldr       pc, [pc, #-4];      \
330           .word     n
331 #endif
332 
333 #endif /* !_ARM_ASM_H_ */
334