cpufunc.h revision 182730
1132718Skan/*- 2132718Skan * Copyright (c) 2001 Jake Burkholder. 3132718Skan * All rights reserved. 4132718Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6132718Skan * modification, are permitted provided that the following conditions 7132718Skan * are met: 8132718Skan * 1. Redistributions of source code must retain the above copyright 9132718Skan * notice, this list of conditions and the following disclaimer. 10132718Skan * 2. Redistributions in binary form must reproduce the above copyright 11132718Skan * notice, this list of conditions and the following disclaimer in the 12132718Skan * documentation and/or other materials provided with the distribution. 13132718Skan * 14132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132718Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132718Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132718Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132718Skan * SUCH DAMAGE. 25132718Skan * 26132718Skan * $FreeBSD: head/sys/sparc64/include/cpufunc.h 182730 2008-09-03 17:39:19Z marius $ 27132718Skan */ 28132718Skan 29132718Skan#ifndef _MACHINE_CPUFUNC_H_ 30132718Skan#define _MACHINE_CPUFUNC_H_ 31169689Skan 32132718Skan#include <machine/asi.h> 33132718Skan#include <machine/pstate.h> 34132718Skan 35132718Skanstruct thread; 36132718Skan 37169689Skan/* 38132718Skan * Membar operand macros for use in other macros when # is a special 39132718Skan * character. Keep these in sync with what the hardware expects. 40132718Skan */ 41132718Skan#define C_Lookaside (0) 42132718Skan#define C_MemIssue (1) 43169689Skan#define C_Sync (2) 44132718Skan#define M_LoadLoad (0) 45132718Skan#define M_StoreLoad (1) 46132718Skan#define M_LoadStore (2) 47132718Skan#define M_StoreStore (3) 48261188Spfg 49261188Spfg#define CMASK_SHIFT (4) 50261188Spfg#define MMASK_SHIFT (0) 51261188Spfg 52261188Spfg#define CMASK_GEN(bit) ((1 << (bit)) << CMASK_SHIFT) 53261188Spfg#define MMASK_GEN(bit) ((1 << (bit)) << MMASK_SHIFT) 54261188Spfg 55132718Skan#define Lookaside CMASK_GEN(C_Lookaside) 56169689Skan#define MemIssue CMASK_GEN(C_MemIssue) 57132718Skan#define Sync CMASK_GEN(C_Sync) 58169689Skan#define LoadLoad MMASK_GEN(M_LoadLoad) 59169689Skan#define StoreLoad MMASK_GEN(M_StoreLoad) 60132718Skan#define LoadStore MMASK_GEN(M_LoadStore) 61132718Skan#define StoreStore MMASK_GEN(M_StoreStore) 62132718Skan 63169689Skan#define casa(rs1, rs2, rd, asi) ({ \ 64132718Skan u_int __rd = (uint32_t)(rd); \ 65132718Skan __asm __volatile("casa [%2] %3, %4, %0" \ 66261188Spfg : "+r" (__rd), "=m" (*rs1) \ 67261188Spfg : "r" (rs1), "n" (asi), "r" (rs2), "m" (*rs1)); \ 68261188Spfg __rd; \ 69261188Spfg}) 70261188Spfg 71261188Spfg#define casxa(rs1, rs2, rd, asi) ({ \ 72261188Spfg u_long __rd = (uint64_t)(rd); \ 73261188Spfg __asm __volatile("casxa [%2] %3, %4, %0" \ 74261188Spfg : "+r" (__rd), "=m" (*rs1) \ 75261188Spfg : "r" (rs1), "n" (asi), "r" (rs2), "m" (*rs1)); \ 76261188Spfg __rd; \ 77261188Spfg}) 78261188Spfg 79261188Spfg#define flush(va) do { \ 80261188Spfg __asm __volatile("flush %0" : : "r" (va)); \ 81261188Spfg} while (0) 82261188Spfg 83261188Spfg#define flushw() do { \ 84261188Spfg __asm __volatile("flushw" : :); \ 85261188Spfg} while (0) 86261188Spfg 87261188Spfg#define mov(val, reg) do { \ 88132718Skan __asm __volatile("mov %0, %" __XSTRING(reg) : : "r" (val)); \ 89132718Skan} while (0) 90169689Skan 91169689Skan/* Generate ld*a/st*a functions for non-constant ASIs. */ 92169689Skan#define LDNC_GEN(tp, o) \ 93132718Skan static __inline tp \ 94132718Skan o ## _nc(caddr_t va, int asi) \ 95261188Spfg { \ 96261188Spfg tp r; \ 97261188Spfg __asm __volatile("wr %2, 0, %%asi;" #o " [%1] %%asi, %0"\ 98261188Spfg : "=r" (r) : "r" (va), "r" (asi)); \ 99261188Spfg return (r); \ 100261188Spfg } 101261188Spfg 102261188SpfgLDNC_GEN(u_char, lduba); 103169689SkanLDNC_GEN(u_short, lduha); 104169689SkanLDNC_GEN(u_int, lduwa); 105261188SpfgLDNC_GEN(u_long, ldxa); 106261188Spfg 107261188Spfg#define LD_GENERIC(va, asi, op, type) ({ \ 108261188Spfg type __r; \ 109169689Skan __asm __volatile(#op " [%1] %2, %0" \ 110169689Skan : "=r" (__r) : "r" (va), "n" (asi)); \ 111169689Skan __r; \ 112169689Skan}) 113261188Spfg 114261188Spfg#define lduba(va, asi) LD_GENERIC(va, asi, lduba, u_char) 115261188Spfg#define lduha(va, asi) LD_GENERIC(va, asi, lduha, u_short) 116261188Spfg#define lduwa(va, asi) LD_GENERIC(va, asi, lduwa, u_int) 117261188Spfg#define ldxa(va, asi) LD_GENERIC(va, asi, ldxa, u_long) 118261188Spfg 119261188Spfg#define STNC_GEN(tp, o) \ 120261188Spfg static __inline void \ 121261188Spfg o ## _nc(caddr_t va, int asi, tp val) \ 122261188Spfg { \ 123169689Skan __asm __volatile("wr %2, 0, %%asi;" #o " %0, [%1] %%asi"\ 124169689Skan : : "r" (val), "r" (va), "r" (asi)); \ 125169689Skan } 126169689Skan 127169689SkanSTNC_GEN(u_char, stba); 128169689SkanSTNC_GEN(u_short, stha); 129169689SkanSTNC_GEN(u_int, stwa); 130169689SkanSTNC_GEN(u_long, stxa); 131169689Skan 132169689Skan#define ST_GENERIC(va, asi, val, op) \ 133169689Skan __asm __volatile(#op " %0, [%1] %2" \ 134132718Skan : : "r" (val), "r" (va), "n" (asi)); \ 135169689Skan 136169689Skan#define stba(va, asi, val) ST_GENERIC(va, asi, val, stba) 137169689Skan#define stha(va, asi, val) ST_GENERIC(va, asi, val, stha) 138169689Skan#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stwa) 139169689Skan#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stxa) 140169689Skan 141132718Skan/* 142132718Skan * Attempt to read from addr, val. If a Data Access Error trap happens, 143132718Skan * they return -1 and the contents of val is undefined. A return of 0 144132718Skan * means no trap happened, and the contents of val is valid. 145132718Skan */ 146169689Skanint fasword8(u_long asi, void *addr, uint8_t *val); 147169689Skanint fasword16(u_long asi, void *addr, uint16_t *val); 148169689Skanint fasword32(u_long asi, void *addr, uint32_t *val); 149169689Skan 150169689Skan#define membar(mask) do { \ 151169689Skan __asm __volatile("membar %0" : : "n" (mask) : "memory"); \ 152169689Skan} while (0) 153169689Skan 154169689Skan#define rd(name) ({ \ 155169689Skan uint64_t __sr; \ 156169689Skan __asm __volatile("rd %%" #name ", %0" : "=r" (__sr) :); \ 157261188Spfg __sr; \ 158261188Spfg}) 159169689Skan 160169689Skan#define wr(name, val, xor) do { \ 161169689Skan __asm __volatile("wr %0, %1, %%" #name \ 162169689Skan : : "r" (val), "rI" (xor)); \ 163169689Skan} while (0) 164261188Spfg 165261188Spfg#define rdpr(name) ({ \ 166169689Skan uint64_t __pr; \ 167169689Skan __asm __volatile("rdpr %%" #name", %0" : "=r" (__pr) :); \ 168261188Spfg __pr; \ 169169689Skan}) 170169689Skan 171169689Skan#define wrpr(name, val, xor) do { \ 172169689Skan __asm __volatile("wrpr %0, %1, %%" #name \ 173261188Spfg : : "r" (val), "rI" (xor)); \ 174261188Spfg} while (0) 175261188Spfg 176261188Spfg/* 177169689Skan * Trick GAS/GCC into compiling access to STICK/STICK_COMPARE independently 178169689Skan * of the selected instruction set. 179169689Skan */ 180169689Skan#define rdstick() rd(asr24) 181169689Skan#define rdstickcmpr() rd(asr25) 182169689Skan#define wrstick(val, xor) wr(asr24, (val), (xor)) 183169689Skan#define wrstickcmpr(val, xor) wr(asr25, (val), (xor)) 184169689Skan 185169689Skan/* 186169689Skan * Macro intended to be used instead of wr(asr23, val, xor) for writing to 187169689Skan * the TICK_COMPARE register in order to avoid a bug in BlackBird CPUs that 188169689Skan * can cause these writes to fail under certain condidtions which in turn 189169689Skan * causes the hardclock to stop. The workaround is to read the TICK_COMPARE 190169689Skan * register back immediately after writing to it with these two instructions 191169689Skan * aligned to a quadword boundary in order to ensure that I$ misses won't 192169689Skan * split them up. 193169689Skan */ 194169689Skan#define wrtickcmpr(val, xor) ({ \ 195169689Skan __asm __volatile( \ 196169689Skan " ba,pt %%xcc, 1f ; " \ 197169689Skan " nop ; " \ 198169689Skan " .align 128 ; " \ 199169689Skan "1: wr %0, %1, %%asr23 ; " \ 200169689Skan " rd %%asr23, %%g0 ; " \ 201169689Skan : : "r" (val), "rI" (xor)); \ 202169689Skan}) 203169689Skan 204169689Skanstatic __inline void 205169689Skanbreakpoint(void) 206169689Skan{ 207169689Skan 208169689Skan __asm __volatile("ta %%xcc, 1" : :); 209169689Skan} 210169689Skan 211169689Skanstatic __inline register_t 212169689Skanintr_disable(void) 213169689Skan{ 214169689Skan register_t s; 215169689Skan 216169689Skan s = rdpr(pstate); 217169689Skan wrpr(pstate, s & ~PSTATE_IE, 0); 218169689Skan return (s); 219169689Skan} 220169689Skan#define intr_restore(s) wrpr(pstate, (s), 0) 221169689Skan 222169689Skan/* 223169689Skan * In some places, it is required that the store is directly followed by a 224169689Skan * membar #Sync. Don't trust the compiler to not insert instructions in 225169689Skan * between. We also need to disable interrupts completely. 226169689Skan */ 227169689Skan#define stxa_sync(va, asi, val) do { \ 228169689Skan register_t s; \ 229169689Skan s = intr_disable(); \ 230169689Skan __asm __volatile("stxa %0, [%1] %2; membar #Sync" \ 231169689Skan : : "r" (val), "r" (va), "n" (asi)); \ 232169689Skan intr_restore(s); \ 233169689Skan} while (0) 234169689Skan 235169689Skanvoid ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len); 236169689Skanvoid ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len); 237169689Skanvoid ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len); 238169689Skanvoid aszero(u_long asi, vm_offset_t dst, size_t len); 239169689Skan 240261188Spfg/* 241261188Spfg * Ultrasparc II doesn't implement popc in hardware. 242261188Spfg */ 243261188Spfg#if 0 244169689Skan#define HAVE_INLINE_FFS 245169689Skan/* 246169689Skan * See page 202 of the SPARC v9 Architecture Manual. 247169689Skan */ 248261188Spfgstatic __inline int 249261188Spfgffs(int mask) 250261188Spfg{ 251261188Spfg int result; 252169689Skan int neg; 253169689Skan int tmp; 254169689Skan 255169689Skan __asm __volatile( 256169689Skan " neg %3, %1 ; " 257169689Skan " xnor %3, %1, %2 ; " 258169689Skan " popc %2, %0 ; " 259169689Skan " movrz %3, %%g0, %0 ; " 260169689Skan : "=r" (result), "=r" (neg), "=r" (tmp) : "r" (mask)); 261169689Skan return (result); 262169689Skan} 263261188Spfg#endif 264261188Spfg 265261188Spfg#undef LDNC_GEN 266261188Spfg#undef STNC_GEN 267169689Skan 268169689Skan#endif /* !_MACHINE_CPUFUNC_H_ */ 269169689Skan