1 /* $NetBSD: asm.h,v 1.56 2025/01/06 10:46:44 martin Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef _PPC_ASM_H_ 35 #define _PPC_ASM_H_ 36 37 #ifdef _LP64 38 39 /* ppc64 is always PIC, r2 is always the TOC */ 40 41 # define PIC_PLT(x) .x 42 43 #else 44 45 # ifdef __PIC__ 46 # define PIC_PROLOGUE XXX 47 # define PIC_EPILOGUE XXX 48 # define PIC_PLT(x) x+32768@plt 49 # ifdef __STDC__ 50 # define PIC_TOCNAME(name) .LCTOC_##name 51 # else 52 # define PIC_TOCNAME(name) .LCTOC_/**/name 53 # endif /* __STDC __*/ 54 # define PIC_TOCSETUP(name, reg) \ 55 .pushsection ".got2","aw" ;\ 56 PIC_TOCNAME(name) = . + 32768 ;\ 57 .popsection ;\ 58 bcl 20,31,1001f ;\ 59 1001: mflr reg ;\ 60 addis reg,reg,PIC_TOCNAME(name)-1001b@ha ;\ 61 addi reg,reg,PIC_TOCNAME(name)-1001b@l 62 # define PIC_GOTSETUP(reg) \ 63 bcl 20,31,2002f ;\ 64 2002: mflr reg ;\ 65 addis reg,reg,_GLOBAL_OFFSET_TABLE_-2002b@ha ;\ 66 addi reg,reg,_GLOBAL_OFFSET_TABLE_-2002b@l 67 # ifdef __STDC__ 68 # define PIC_GOT(x) XXX 69 # define PIC_GOTOFF(x) XXX 70 # else /* not __STDC__ */ 71 # define PIC_GOT(x) XXX 72 # define PIC_GOTOFF(x) XXX 73 # endif /* __STDC__ */ 74 # else /* !__PIC__ */ 75 # define PIC_PROLOGUE 76 # define PIC_EPILOGUE 77 # define PIC_PLT(x) x 78 # define PIC_GOT(x) x 79 # define PIC_GOTOFF(x) x 80 # define PIC_GOTSETUP(r) 81 # define PIC_TOCSETUP(n, r) 82 # endif /* __PIC__ */ 83 84 #endif /* _LP64 */ 85 86 #define _C_LABEL(x) x 87 #define _ASM_LABEL(x) x 88 89 #define _GLOBAL(x) \ 90 .data; .align 2; .globl x; x: 91 92 #ifdef GPROF 93 # define _PROF_PROLOGUE mflr 0; stw 0,4(1); bl _mcount 94 #else 95 # define _PROF_PROLOGUE 96 #endif 97 98 #ifdef _LP64 99 100 # define SF_HEADER_SZ 48 101 # define SF_PARAM_SZ 64 102 # define SF_SZ (SF_HEADER_SZ + SF_PARAM_SZ) 103 104 # define SF_SP 0 105 # define SF_CR 8 106 # define SF_LR 16 107 # define SF_COMP 24 108 # define SF_LD 32 109 # define SF_TOC 40 110 # define SF_PARAM SF_HEADER_SZ 111 # define SF_ALIGN(x) (((x) + 0xf) & ~0xf) 112 113 # define _XENTRY(y) \ 114 .globl y; \ 115 .pushsection ".opd","aw"; \ 116 .align 3; \ 117 y: .quad .##y,.TOC.@tocbase,0; \ 118 .popsection; \ 119 .size y,24; \ 120 .type .##y,@function; \ 121 .globl .##y; \ 122 .align 3; \ 123 .##y: 124 125 #define _ENTRY(x) .text; _XENTRY(x) 126 127 # define ENTRY(y) _ENTRY(y) 128 129 # define END(y) .size .##y,. - .##y 130 131 # define CALL(y) \ 132 bl .y; \ 133 nop 134 135 # define ENTRY_NOPROFILE(y) ENTRY(y) 136 # define ASENTRY(y) ENTRY(y) 137 #else /* !_LP64 */ 138 139 # define _XENTRY(x) .align 2; .globl x; .type x,@function; x: 140 # define _ENTRY(x) .text; _XENTRY(x) 141 142 # define ENTRY(y) _ENTRY(_C_LABEL(y)); _PROF_PROLOGUE 143 144 # define END(y) .size _C_LABEL(y),.-_C_LABEL(y) 145 146 # define CALL(y) \ 147 bl y 148 149 # define ENTRY_NOPROFILE(y) _ENTRY(_C_LABEL(y)) 150 # define ASENTRY(y) _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE 151 #endif /* _LP64 */ 152 153 #define GLOBAL(y) _GLOBAL(_C_LABEL(y)) 154 155 #define ASMSTR .asciz 156 157 #undef __RCSID 158 159 #define RCSID(x) __RCSID(x) 160 #ifdef _NETBSD_REVISIONID 161 #define __RCSID(x) .pushsection ".ident","MS",@progbits,1; \ 162 .asciz x; \ 163 .ascii "$"; .ascii "NetBSD: "; .ascii __FILE__; \ 164 .ascii " "; .ascii _NETBSD_REVISIONID; \ 165 .asciz " $"; \ 166 .popsection 167 #else 168 #define __RCSID(x) .pushsection ".ident","MS",@progbits,1; \ 169 .asciz x; \ 170 .popsection 171 #endif 172 173 #ifdef __ELF__ 174 # define WEAK_ALIAS(alias,sym) \ 175 .weak alias; \ 176 alias = sym 177 #endif /* __ELF__ */ 178 /* 179 * STRONG_ALIAS: create a strong alias. 180 */ 181 #define STRONG_ALIAS(alias,sym) \ 182 .globl alias; \ 183 alias = sym 184 185 #ifdef __STDC__ 186 # define WARN_REFERENCES(sym,msg) \ 187 .pushsection .gnu.warning. ## sym; \ 188 .ascii msg; \ 189 .popsection 190 #else 191 # define WARN_REFERENCES(sym,msg) \ 192 .pushsection .gnu.warning./**/sym; \ 193 .ascii msg; \ 194 .popsection 195 #endif /* __STDC__ */ 196 197 #ifdef _KERNEL 198 /* 199 * Get cpu_info pointer for current processor. Always in SPRG0. *ALWAYS* 200 */ 201 # define GET_CPUINFO(r) mfsprg r,0 202 /* 203 * IN: 204 * R4[er] = first free byte beyond end/esym. 205 * 206 * OUT: 207 * R1[sp] = new kernel stack 208 * R4[er] = kernelend 209 */ 210 211 # ifdef CI_INTSTK 212 # define INIT_CPUINFO_INTSTK(er,tmp1) \ 213 addis er,er,INTSTK@ha; \ 214 addi er,er,INTSTK@l; \ 215 stptr er,CI_INTSTK(tmp1) 216 # else 217 # define INIT_CPUINFO_INTSTK(er,tmp1) /* nothing */ 218 # endif /* CI_INTSTK */ 219 220 /* 221 * We use lis/ori instead of lis/addi in case tmp2 is r0. 222 */ 223 # define INIT_CPUINFO(er,sp,tmp1,tmp2) \ 224 li tmp1,PAGE_MASK; \ 225 add er,er,tmp1; \ 226 andc er,er,tmp1; /* page align */ \ 227 lis tmp1,_C_LABEL(cpu_info)@ha; \ 228 addi tmp1,tmp1,_C_LABEL(cpu_info)@l; \ 229 mtsprg0 tmp1; /* save for later use */ \ 230 INIT_CPUINFO_INTSTK(er,tmp1); \ 231 lis tmp2,_C_LABEL(emptyidlespin)@h; \ 232 ori tmp2,tmp2,_C_LABEL(emptyidlespin)@l; \ 233 stptr tmp2,CI_IDLESPIN(tmp1); \ 234 li tmp2,-1; \ 235 stint tmp2,CI_IDEPTH(tmp1); \ 236 li tmp2,0; \ 237 lis %r13,_C_LABEL(lwp0)@h; \ 238 ori %r13,%r13,_C_LABEL(lwp0)@l; \ 239 stptr er,L_PCB(%r13); /* XXXuvm_lwp_getuarea */ \ 240 stptr tmp1,L_CPU(%r13); \ 241 addis er,er,USPACE@ha; /* stackpointer for lwp0 */ \ 242 addi er,er,USPACE@l; /* stackpointer for lwp0 */ \ 243 addi sp,er,-FRAMELEN-CALLFRAMELEN; /* stackpointer for lwp0 */ \ 244 stptr sp,L_MD_UTF(%r13); /* save in lwp0.l_md.md_utf */ \ 245 /* er = end of mem reserved for kernel */ \ 246 li tmp2,0; \ 247 stptr tmp2,-CALLFRAMELEN(er); /* end of stack chain */ \ 248 stptru tmp2,-CALLFRAMELEN(sp) /* end of stack chain */ 249 250 #endif /* _KERNEL */ 251 252 253 #if defined(_REGNAMES) && (defined(_KERNEL) || defined(_STANDALONE)) 254 /* Condition Register Bit Fields */ 255 # define cr0 0 256 # define cr1 1 257 # define cr2 2 258 # define cr3 3 259 # define cr4 4 260 # define cr5 5 261 # define cr6 6 262 # define cr7 7 263 /* General Purpose Registers (GPRs) */ 264 # define r0 0 265 # define r1 1 266 # define r2 2 267 # define r3 3 268 # define r4 4 269 # define r5 5 270 # define r6 6 271 # define r7 7 272 # define r8 8 273 # define r9 9 274 # define r10 10 275 # define r11 11 276 # define r12 12 277 # define r13 13 278 # define r14 14 279 # define r15 15 280 # define r16 16 281 # define r17 17 282 # define r18 18 283 # define r19 19 284 # define r20 20 285 # define r21 21 286 # define r22 22 287 # define r23 23 288 # define r24 24 289 # define r25 25 290 # define r26 26 291 # define r27 27 292 # define r28 28 293 # define r29 29 294 # define r30 30 295 # define r31 31 296 /* Floating Point Registers (FPRs) */ 297 # define fr0 0 298 # define fr1 1 299 # define fr2 2 300 # define fr3 3 301 # define fr4 4 302 # define fr5 5 303 # define fr6 6 304 # define fr7 7 305 # define fr8 8 306 # define fr9 9 307 # define fr10 10 308 # define fr11 11 309 # define fr12 12 310 # define fr13 13 311 # define fr14 14 312 # define fr15 15 313 # define fr16 16 314 # define fr17 17 315 # define fr18 18 316 # define fr19 19 317 # define fr20 20 318 # define fr21 21 319 # define fr22 22 320 # define fr23 23 321 # define fr24 24 322 # define fr25 25 323 # define fr26 26 324 # define fr27 27 325 # define fr28 28 326 # define fr29 29 327 # define fr30 30 328 # define fr31 31 329 #endif /* _REGNAMES && (_KERNEL || _STANDALONE) */ 330 331 /* 332 * Add some pseudo instructions to made sharing of assembly versions of 333 * ILP32 and LP64 code possible. 334 */ 335 #define ldint lwz /* not needed but for completeness */ 336 #define ldintu lwzu /* not needed but for completeness */ 337 #define stint stw /* not needed but for completeness */ 338 #define stintu stwu /* not needed but for completeness */ 339 340 #ifndef _LP64 341 342 # define ldlong lwz /* load "C" long */ 343 # define ldlongu lwzu /* load "C" long with update */ 344 # define stlong stw /* load "C" long */ 345 # define stlongu stwu /* load "C" long with update */ 346 # define ldptr lwz /* load "C" pointer */ 347 # define ldptru lwzu /* load "C" pointer with update */ 348 # define stptr stw /* load "C" pointer */ 349 # define stptru stwu /* load "C" pointer with update */ 350 # define ldreg lwz /* load PPC general register */ 351 # define ldregu lwzu /* load PPC general register with update */ 352 # define streg stw /* load PPC general register */ 353 # define stregu stwu /* load PPC general register with update */ 354 # define SZREG 4 /* 4 byte registers */ 355 # define P2SZREG 2 356 357 # define lptrarx lwarx /* load "C" pointer with reservation */ 358 # define llongarx lwarx /* load "C" long with reservation */ 359 # define lregarx lwarx /* load PPC general register with reservation */ 360 361 # define stptrcx stwcx /* store "C" pointer conditional */ 362 # define stlongcx stwcx /* store "C" long conditional */ 363 # define stregcx stwcx /* store PPC general register conditional */ 364 365 # define clrrptri clrrwi /* clear right "C" pointer immediate */ 366 # define clrrlongi clrrwi /* clear right "C" long immediate */ 367 # define clrrregi clrrwi /* clear right PPC general register immediate */ 368 369 # define cmpptr cmpw 370 # define cmplong cmpw 371 # define cmpreg cmpw 372 # define cmpptri cmpwi 373 # define cmplongi cmpwi 374 # define cmpregi cmpwi 375 # define cmpptrl cmplw 376 # define cmplongl cmplw 377 # define cmpregl cmplw 378 # define cmpptrli cmplwi 379 # define cmplongli cmplwi 380 # define cmpregli cmplwi 381 382 #else /* _LP64 */ 383 384 # define ldlong ld /* load "C" long */ 385 # define ldlongu ldu /* load "C" long with update */ 386 # define stlong std /* store "C" long */ 387 # define stlongu stdu /* store "C" long with update */ 388 # define ldptr ld /* load "C" pointer */ 389 # define ldptru ldu /* load "C" pointer with update */ 390 # define stptr std /* store "C" pointer */ 391 # define stptru stdu /* store "C" pointer with update */ 392 # define ldreg ld /* load PPC general register */ 393 # define ldregu ldu /* load PPC general register with update */ 394 # define streg std /* store PPC general register */ 395 # define stregu stdu /* store PPC general register with update */ 396 /* redefined this to force an error on PPC64 to catch their use. */ 397 # define lmw lmd /* load multiple PPC general registers */ 398 # define stmw stmd /* store multiple PPC general registers */ 399 # define SZREG 8 /* 8 byte registers */ 400 # define P2SZREG 3 401 402 # define lptrarx ldarx /* load "C" pointer with reservation */ 403 # define llongarx ldarx /* load "C" long with reservation */ 404 # define lregarx ldarx /* load PPC general register with reservation */ 405 406 # define stptrcx stdcx /* store "C" pointer conditional */ 407 # define stlongcx stdcx /* store "C" long conditional */ 408 # define stregax stdcx /* store PPC general register conditional */ 409 410 # define clrrptri clrrdi /* clear right "C" pointer immediate */ 411 # define clrrlongi clrrdi /* clear right "C" long immediate */ 412 # define clrrregi clrrdi /* clear right PPC general register immediate */ 413 414 # define cmpptr cmpd 415 # define cmplong cmpd 416 # define cmpreg cmpd 417 # define cmpptri cmpdi 418 # define cmplongi cmpdi 419 # define cmpregi cmpdi 420 # define cmpptrl cmpld 421 # define cmplongl cmpld 422 # define cmpregl cmpld 423 # define cmpptrli cmpldi 424 # define cmplongli cmpldi 425 # define cmpregli cmpldi 426 427 #endif /* _LP64 */ 428 429 #ifdef _LOCORE 430 .macro stmd r,dst 431 i = 0 432 .rept 32-\r 433 std i+\r, i*8+\dst 434 i = i + 1 435 .endr 436 .endm 437 438 .macro lmd r,dst 439 i = 0 440 .rept 32-\r 441 ld i+\r, i*8+\dst 442 i = i + 1 443 .endr 444 .endm 445 #endif /* _LOCORE */ 446 447 #if defined(IBM405_ERRATA77) || \ 448 ((defined(_MODULE) || !defined(_KERNEL)) && !defined(_LP64)) 449 /* 450 * Workaround for IBM405 Errata 77 (CPU_210): interrupted stwcx. may 451 * errantly write data to memory 452 * 453 * (1) Insert dcbt before every stwcx. instruction 454 * (2) Insert sync before every rfi/rfci instruction 455 */ 456 #define IBM405_ERRATA77_DCBT(ra, rb) dcbt ra,rb 457 #define IBM405_ERRATA77_SYNC sync 458 #else 459 #define IBM405_ERRATA77_DCBT(ra, rb) /* nothing */ 460 #define IBM405_ERRATA77_SYNC /* nothing */ 461 #endif 462 463 #endif /* !_PPC_ASM_H_ */ 464