1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2001 Jake Burkholder. 5 * Copyright (c) 2011 Marius Strobl <marius@FreeBSD.org> 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: stable/12/sys/sparc64/include/asmacros.h 326262 2017-11-27 15:10:39Z pfg $ 30 */ 31 32 #ifndef _MACHINE_ASMACROS_H_ 33 #define _MACHINE_ASMACROS_H_ 34 35 #ifdef _KERNEL 36 37 /* 38 * Normal and alternate %g6 point to the pcb of the current process. Normal, 39 * alternate and interrupt %g7 point to per-cpu data. 40 */ 41 #define PCB_REG %g6 42 #define PCPU_REG %g7 43 44 /* 45 * Alternate %g5 points to a per-cpu panic stack, which is used as a last 46 * resort, and for temporarily saving alternate globals. 47 */ 48 #define ASP_REG %g5 49 50 #ifdef LOCORE 51 52 /* 53 * Atomically decrement an integer in memory. 54 */ 55 #define ATOMIC_DEC_INT(r1, r2, r3) \ 56 lduw [r1], r2 ; \ 57 9: sub r2, 1, r3 ; \ 58 casa [r1] ASI_N, r2, r3 ; \ 59 cmp r2, r3 ; \ 60 bne,pn %icc, 9b ; \ 61 mov r3, r2 62 63 /* 64 * Atomically increment an integer in memory. 65 */ 66 #define ATOMIC_INC_INT(r1, r2, r3) \ 67 lduw [r1], r2 ; \ 68 9: add r2, 1, r3 ; \ 69 casa [r1] ASI_N, r2, r3 ; \ 70 cmp r2, r3 ; \ 71 bne,pn %icc, 9b ; \ 72 mov r3, r2 73 74 /* 75 * Atomically increment a long in memory. 76 */ 77 #define ATOMIC_INC_LONG(r1, r2, r3) \ 78 ldx [r1], r2 ; \ 79 9: add r2, 1, r3 ; \ 80 casxa [r1] ASI_N, r2, r3 ; \ 81 cmp r2, r3 ; \ 82 bne,pn %xcc, 9b ; \ 83 mov r3, r2 84 85 /* 86 * Atomically clear a number of bits of an integer in memory. 87 */ 88 #define ATOMIC_CLEAR_INT(r1, r2, r3, bits) \ 89 lduw [r1], r2 ; \ 90 9: andn r2, bits, r3 ; \ 91 casa [r1] ASI_N, r2, r3 ; \ 92 cmp r2, r3 ; \ 93 bne,pn %icc, 9b ; \ 94 mov r3, r2 95 96 /* 97 * Atomically clear a number of bits of a long in memory. 98 */ 99 #define ATOMIC_CLEAR_LONG(r1, r2, r3, bits) \ 100 ldx [r1], r2 ; \ 101 9: andn r2, bits, r3 ; \ 102 casxa [r1] ASI_N, r2, r3 ; \ 103 cmp r2, r3 ; \ 104 bne,pn %xcc, 9b ; \ 105 mov r3, r2 106 107 /* 108 * Atomically load an integer from memory. 109 */ 110 #define ATOMIC_LOAD_INT(r1, val) \ 111 clr val ; \ 112 casa [r1] ASI_N, %g0, val 113 114 /* 115 * Atomically load a long from memory. 116 */ 117 #define ATOMIC_LOAD_LONG(r1, val) \ 118 clr val ; \ 119 casxa [r1] ASI_N, %g0, val 120 121 /* 122 * Atomically set a number of bits of an integer in memory. 123 */ 124 #define ATOMIC_SET_INT(r1, r2, r3, bits) \ 125 lduw [r1], r2 ; \ 126 9: or r2, bits, r3 ; \ 127 casa [r1] ASI_N, r2, r3 ; \ 128 cmp r2, r3 ; \ 129 bne,pn %icc, 9b ; \ 130 mov r3, r2 131 132 /* 133 * Atomically set a number of bits of a long in memory. 134 */ 135 #define ATOMIC_SET_LONG(r1, r2, r3, bits) \ 136 ldx [r1], r2 ; \ 137 9: or r2, bits, r3 ; \ 138 casxa [r1] ASI_N, r2, r3 ; \ 139 cmp r2, r3 ; \ 140 bne,pn %xcc, 9b ; \ 141 mov r3, r2 142 143 /* 144 * Atomically store an integer in memory. 145 */ 146 #define ATOMIC_STORE_INT(r1, r2, r3, val) \ 147 lduw [r1], r2 ; \ 148 9: mov val, r3 ; \ 149 casa [r1] ASI_N, r2, r3 ; \ 150 cmp r2, r3 ; \ 151 bne,pn %icc, 9b ; \ 152 mov r3, r2 153 154 /* 155 * Atomically store a long in memory. 156 */ 157 #define ATOMIC_STORE_LONG(r1, r2, r3, val) \ 158 ldx [r1], r2 ; \ 159 9: mov val, r3 ; \ 160 casxa [r1] ASI_N, r2, r3 ; \ 161 cmp r2, r3 ; \ 162 bne,pn %xcc, 9b ; \ 163 mov r3, r2 164 165 #define PCPU(member) PCPU_REG + PC_ ## member 166 #define PCPU_ADDR(member, reg) \ 167 add PCPU_REG, PC_ ## member, reg 168 169 #define DEBUGGER() \ 170 ta %xcc, 1 171 172 #define PANIC(msg, r1) \ 173 .sect .rodata ; \ 174 9: .asciz msg ; \ 175 .previous ; \ 176 SET(9b, r1, %o0) ; \ 177 call panic ; \ 178 nop 179 180 #ifdef INVARIANTS 181 #define KASSERT(r1, msg) \ 182 brnz,pt r1, 8f ; \ 183 nop ; \ 184 PANIC(msg, r1) ; \ 185 8: 186 #else 187 #define KASSERT(r1, msg) 188 #endif 189 190 #define PUTS(msg, r1) \ 191 .sect .rodata ; \ 192 9: .asciz msg ; \ 193 .previous ; \ 194 SET(9b, r1, %o0) ; \ 195 call printf ; \ 196 nop 197 198 #define _ALIGN_DATA .align 8 199 200 #define DATA(name) \ 201 .data ; \ 202 _ALIGN_DATA ; \ 203 .globl name ; \ 204 .type name, @object ; \ 205 name: 206 207 #define EMPTY 208 209 /* 210 * Generate atomic compare and swap, load and store instructions for the 211 * corresponding width and ASI (or not). Note that we want to evaluate the 212 * macro args before concatenating, so that EMPTY really turns into nothing. 213 */ 214 #define _LD(w, a) ld ## w ## a 215 #define _ST(w, a) st ## w ## a 216 #define _CAS(w, a) cas ## w ## a 217 218 #define LD(w, a) _LD(w, a) 219 #define ST(w, a) _ST(w, a) 220 #define CAS(w, a) _CAS(w, a) 221 222 #endif /* LOCORE */ 223 224 #endif /* _KERNEL */ 225 226 #endif /* !_MACHINE_ASMACROS_H_ */ 227