cpufunc.h revision 181701
150477Speter/*- 211394Sswallace * Copyright (c) 2001 Jake Burkholder. 311394Sswallace * All rights reserved. 411394Sswallace * 511394Sswallace * Redistribution and use in source and binary forms, with or without 611394Sswallace * modification, are permitted provided that the following conditions 7155403Srwatson * are met: 811394Sswallace * 1. Redistributions of source code must retain the above copyright 9146806Srwatson * notice, this list of conditions and the following disclaimer. 10146806Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11146806Srwatson * notice, this list of conditions and the following disclaimer in the 12146806Srwatson * documentation and/or other materials provided with the distribution. 13146806Srwatson * 1411397Sswallace * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1511397Sswallace * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1611397Sswallace * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1711394Sswallace * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1811397Sswallace * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1911397Sswallace * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2011394Sswallace * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2111394Sswallace * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2211394Sswallace * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2311394Sswallace * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2411397Sswallace * SUCH DAMAGE. 2511397Sswallace * 2611394Sswallace * $FreeBSD: head/sys/sparc64/include/cpufunc.h 181701 2008-08-13 20:30:28Z marius $ 2711394Sswallace */ 2811394Sswallace 2911397Sswallace#ifndef _MACHINE_CPUFUNC_H_ 3011397Sswallace#define _MACHINE_CPUFUNC_H_ 3111397Sswallace 3211397Sswallace#include <machine/asi.h> 3311397Sswallace#include <machine/pstate.h> 3411397Sswallace 3511397Sswallacestruct thread; 3611394Sswallace 3711394Sswallace/* 38147974Sjhb * Membar operand macros for use in other macros when # is a special 39155403Srwatson * character. Keep these in sync with what the hardware expects. 40146806Srwatson */ 41155403Srwatson#define C_Lookaside (0) 42146806Srwatson#define C_MemIssue (1) 43146806Srwatson#define C_Sync (2) 44146806Srwatson#define M_LoadLoad (0) 45146806Srwatson#define M_StoreLoad (1) 46155403Srwatson#define M_LoadStore (2) 47146806Srwatson#define M_StoreStore (3) 48155403Srwatson 49155403Srwatson#define CMASK_SHIFT (4) 50155403Srwatson#define MMASK_SHIFT (0) 51155403Srwatson 52155403Srwatson#define CMASK_GEN(bit) ((1 << (bit)) << CMASK_SHIFT) 53155403Srwatson#define MMASK_GEN(bit) ((1 << (bit)) << MMASK_SHIFT) 54155403Srwatson 55147974Sjhb#define Lookaside CMASK_GEN(C_Lookaside) 56155403Srwatson#define MemIssue CMASK_GEN(C_MemIssue) 57146806Srwatson#define Sync CMASK_GEN(C_Sync) 58155403Srwatson#define LoadLoad MMASK_GEN(M_LoadLoad) 59155403Srwatson#define StoreLoad MMASK_GEN(M_StoreLoad) 60146806Srwatson#define LoadStore MMASK_GEN(M_LoadStore) 61147974Sjhb#define StoreStore MMASK_GEN(M_StoreStore) 62155403Srwatson 63146806Srwatson#define casa(rs1, rs2, rd, asi) ({ \ 64155403Srwatson u_int __rd = (uint32_t)(rd); \ 65146806Srwatson __asm __volatile("casa [%2] %3, %4, %0" \ 66146806Srwatson : "+r" (__rd), "=m" (*rs1) \ 67155403Srwatson : "r" (rs1), "n" (asi), "r" (rs2), "m" (*rs1)); \ 68146806Srwatson __rd; \ 69146806Srwatson}) 70155403Srwatson 71155403Srwatson#define casxa(rs1, rs2, rd, asi) ({ \ 72155403Srwatson u_long __rd = (uint64_t)(rd); \ 73155403Srwatson __asm __volatile("casxa [%2] %3, %4, %0" \ 74155403Srwatson : "+r" (__rd), "=m" (*rs1) \ 75146806Srwatson : "r" (rs1), "n" (asi), "r" (rs2), "m" (*rs1)); \ 76147974Sjhb __rd; \ 77155403Srwatson}) 78146806Srwatson 79146806Srwatson#define flush(va) do { \ 80147974Sjhb __asm __volatile("flush %0" : : "r" (va)); \ 81146806Srwatson} while (0) 82147974Sjhb 83146806Srwatson#define flushw() do { \ 84147974Sjhb __asm __volatile("flushw" : :); \ 85146806Srwatson} while (0) 86155403Srwatson 87155403Srwatson#define mov(val, reg) do { \ 88155403Srwatson __asm __volatile("mov %0, %" __XSTRING(reg) : : "r" (val)); \ 89146806Srwatson} while (0) 90146806Srwatson 91147974Sjhb/* Generate ld*a/st*a functions for non-constant ASIs. */ 92155403Srwatson#define LDNC_GEN(tp, o) \ 93155403Srwatson static __inline tp \ 94146806Srwatson o ## _nc(caddr_t va, int asi) \ 95146806Srwatson { \ 96146806Srwatson tp r; \ 97146806Srwatson __asm __volatile("wr %2, 0, %%asi;" #o " [%1] %%asi, %0"\ 98147974Sjhb : "=r" (r) : "r" (va), "r" (asi)); \ 99146806Srwatson return (r); \ 100146806Srwatson } 101155403Srwatson 102147974SjhbLDNC_GEN(u_char, lduba); 103155403SrwatsonLDNC_GEN(u_short, lduha); 104146806SrwatsonLDNC_GEN(u_int, lduwa); 105147974SjhbLDNC_GEN(u_long, ldxa); 106155403Srwatson 107155403Srwatson#define LD_GENERIC(va, asi, op, type) ({ \ 108147974Sjhb type __r; \ 109155403Srwatson __asm __volatile(#op " [%1] %2, %0" \ 110146806Srwatson : "=r" (__r) : "r" (va), "n" (asi)); \ 111147974Sjhb __r; \ 112146806Srwatson}) 113155403Srwatson 114146806Srwatson#define lduba(va, asi) LD_GENERIC(va, asi, lduba, u_char) 115155403Srwatson#define lduha(va, asi) LD_GENERIC(va, asi, lduha, u_short) 116146806Srwatson#define lduwa(va, asi) LD_GENERIC(va, asi, lduwa, u_int) 117155403Srwatson#define ldxa(va, asi) LD_GENERIC(va, asi, ldxa, u_long) 118146806Srwatson 119147974Sjhb#define STNC_GEN(tp, o) \ 120146806Srwatson static __inline void \ 121146806Srwatson o ## _nc(caddr_t va, int asi, tp val) \ 122147974Sjhb { \ 123146806Srwatson __asm __volatile("wr %2, 0, %%asi;" #o " %0, [%1] %%asi"\ 124155403Srwatson : : "r" (val), "r" (va), "r" (asi)); \ 125155403Srwatson } 126146806Srwatson 127155403SrwatsonSTNC_GEN(u_char, stba); 128155403SrwatsonSTNC_GEN(u_short, stha); 129155403SrwatsonSTNC_GEN(u_int, stwa); 130146806SrwatsonSTNC_GEN(u_long, stxa); 131146806Srwatson 132146806Srwatson#define ST_GENERIC(va, asi, val, op) \ 133146806Srwatson __asm __volatile(#op " %0, [%1] %2" \ 134146806Srwatson : : "r" (val), "r" (va), "n" (asi)); \ 135146806Srwatson 136146806Srwatson#define stba(va, asi, val) ST_GENERIC(va, asi, val, stba) 137146806Srwatson#define stha(va, asi, val) ST_GENERIC(va, asi, val, stha) 138146806Srwatson#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stwa) 139146806Srwatson#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stxa) 140146806Srwatson 141146806Srwatson/* 142146806Srwatson * Attempt to read from addr, val. If a Data Access Error trap happens, 143146806Srwatson * they return -1 and the contents of val is undefined. A return of 0 144146806Srwatson * means no trap happened, and the contents of val is valid. 145146806Srwatson */ 146146806Srwatsonint fasword8(u_long asi, void *addr, uint8_t *val); 147155403Srwatsonint fasword16(u_long asi, void *addr, uint16_t *val); 148155403Srwatsonint fasword32(u_long asi, void *addr, uint32_t *val); 149155403Srwatson 150146806Srwatson#define membar(mask) do { \ 151146806Srwatson __asm __volatile("membar %0" : : "n" (mask) : "memory"); \ 152146806Srwatson} while (0) 153147974Sjhb 154146806Srwatson#define rd(name) ({ \ 155155403Srwatson uint64_t __sr; \ 156146806Srwatson __asm __volatile("rd %%" #name ", %0" : "=r" (__sr) :); \ 157146806Srwatson __sr; \ 158155403Srwatson}) 159146806Srwatson 160146806Srwatson#define wr(name, val, xor) do { \ 161155403Srwatson __asm __volatile("wr %0, %1, %%" #name \ 162146806Srwatson : : "r" (val), "rI" (xor)); \ 163146806Srwatson} while (0) 164147974Sjhb 165146806Srwatson#define rdpr(name) ({ \ 166155403Srwatson uint64_t __pr; \ 167146806Srwatson __asm __volatile("rdpr %%" #name", %0" : "=r" (__pr) :); \ 168155403Srwatson __pr; \ 169146806Srwatson}) 170155403Srwatson 171146806Srwatson#define wrpr(name, val, xor) do { \ 172146806Srwatson __asm __volatile("wrpr %0, %1, %%" #name \ 173146806Srwatson : : "r" (val), "rI" (xor)); \ 174146806Srwatson} while (0) 175146806Srwatson 176146806Srwatson/* 177146806Srwatson * Macro intended to be used instead of wr(asr23, val, xor) for writing to 178146806Srwatson * the TICK_COMPARE register in order to avoid a bug in BlackBird CPUs that 179146806Srwatson * can cause these writes to fail under certain condidtions which in turn 180146806Srwatson * causes the hardclock to stop. The workaround is to perform the write 181146806Srwatson * at the beginning of an I-Cache line directly followed by a dummy read. 182146806Srwatson */ 183146806Srwatson#define wrtickcmpr(val, xor) ({ \ 184146806Srwatson __asm __volatile( \ 185147974Sjhb " ba,pt %%xcc, 1f ; " \ 186146806Srwatson " nop ; " \ 187146806Srwatson " .align 64 ; " \ 188146806Srwatson "1: wr %0, %1, %%asr23 ; " \ 189146806Srwatson " rd %%asr23, %%g0 ; " \ 190146806Srwatson : : "r" (val), "rI" (xor)); \ 191146806Srwatson}) 192146806Srwatson 193146806Srwatsonstatic __inline void 194146806Srwatsonbreakpoint(void) 195146806Srwatson{ 196146806Srwatson 197146806Srwatson __asm __volatile("ta %%xcc, 1" : :); 198146806Srwatson} 199146806Srwatson 200146806Srwatsonstatic __inline register_t 201146806Srwatsonintr_disable(void) 202146806Srwatson{ 203146806Srwatson register_t s; 204146806Srwatson 205146806Srwatson s = rdpr(pstate); 206146806Srwatson wrpr(pstate, s & ~PSTATE_IE, 0); 207146806Srwatson return (s); 208} 209#define intr_restore(s) wrpr(pstate, (s), 0) 210 211/* 212 * In some places, it is required that the store is directly followed by a 213 * membar #Sync. Don't trust the compiler to not insert instructions in 214 * between. We also need to disable interrupts completely. 215 */ 216#define stxa_sync(va, asi, val) do { \ 217 register_t s; \ 218 s = intr_disable(); \ 219 __asm __volatile("stxa %0, [%1] %2; membar #Sync" \ 220 : : "r" (val), "r" (va), "n" (asi)); \ 221 intr_restore(s); \ 222} while (0) 223 224void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len); 225void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len); 226void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len); 227void aszero(u_long asi, vm_offset_t dst, size_t len); 228 229/* 230 * Ultrasparc II doesn't implement popc in hardware. 231 */ 232#if 0 233#define HAVE_INLINE_FFS 234/* 235 * See page 202 of the SPARC v9 Architecture Manual. 236 */ 237static __inline int 238ffs(int mask) 239{ 240 int result; 241 int neg; 242 int tmp; 243 244 __asm __volatile( 245 " neg %3, %1 ; " 246 " xnor %3, %1, %2 ; " 247 " popc %2, %0 ; " 248 " movrz %3, %%g0, %0 ; " 249 : "=r" (result), "=r" (neg), "=r" (tmp) : "r" (mask)); 250 return (result); 251} 252#endif 253 254#undef LDNC_GEN 255#undef STNC_GEN 256 257#endif /* !_MACHINE_CPUFUNC_H_ */ 258