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