cpufunc.h revision 116659
1284194Sdelphij/*- 2284194Sdelphij * Copyright (c) 2001 Jake Burkholder. 3284194Sdelphij * All rights reserved. 4284194Sdelphij * 5284194Sdelphij * Redistribution and use in source and binary forms, with or without 6284194Sdelphij * modification, are permitted provided that the following conditions 7284194Sdelphij * are met: 8284194Sdelphij * 1. Redistributions of source code must retain the above copyright 9284194Sdelphij * notice, this list of conditions and the following disclaimer. 10284194Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 11284194Sdelphij * notice, this list of conditions and the following disclaimer in the 12284194Sdelphij * documentation and/or other materials provided with the distribution. 13284194Sdelphij * 14284194Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15284194Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16284194Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17284194Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18284194Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19284194Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20284194Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21284194Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22284194Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23284194Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24284194Sdelphij * SUCH DAMAGE. 25284194Sdelphij * 26284194Sdelphij * $FreeBSD: head/sys/sparc64/include/cpufunc.h 116659 2003-06-22 01:26:08Z jmg $ 27284194Sdelphij */ 28284194Sdelphij 29284194Sdelphij#ifndef _MACHINE_CPUFUNC_H_ 30284194Sdelphij#define _MACHINE_CPUFUNC_H_ 31284194Sdelphij 32284194Sdelphij#include <machine/asi.h> 33284194Sdelphij#include <machine/pstate.h> 34284194Sdelphij 35284194Sdelphijstruct thread; 36284194Sdelphij 37284194Sdelphij/* 38284194Sdelphij * membar operand macros for use in other macros when # is a special 39284194Sdelphij * character. Keep these in sync with what the hardware expects. 40284194Sdelphij */ 41284194Sdelphij#define C_Lookaside (0) 42284194Sdelphij#define C_MemIssue (1) 43284194Sdelphij#define C_Sync (2) 44284194Sdelphij#define M_LoadLoad (0) 45284194Sdelphij#define M_StoreLoad (1) 46284194Sdelphij#define M_LoadStore (2) 47284194Sdelphij#define M_StoreStore (3) 48284194Sdelphij 49284194Sdelphij#define CMASK_SHIFT (4) 50284194Sdelphij#define MMASK_SHIFT (0) 51284194Sdelphij 52284194Sdelphij#define CMASK_GEN(bit) ((1 << (bit)) << CMASK_SHIFT) 53284194Sdelphij#define MMASK_GEN(bit) ((1 << (bit)) << MMASK_SHIFT) 54284194Sdelphij 55284194Sdelphij#define Lookaside CMASK_GEN(C_Lookaside) 56284194Sdelphij#define MemIssue CMASK_GEN(C_MemIssue) 57284194Sdelphij#define Sync CMASK_GEN(C_Sync) 58284194Sdelphij#define LoadLoad MMASK_GEN(M_LoadLoad) 59284194Sdelphij#define StoreLoad MMASK_GEN(M_StoreLoad) 60284194Sdelphij#define LoadStore MMASK_GEN(M_LoadStore) 61284194Sdelphij#define StoreStore MMASK_GEN(M_StoreStore) 62284194Sdelphij 63284194Sdelphij#define casa(rs1, rs2, rd, asi) ({ \ 64284194Sdelphij u_int __rd = (u_int32_t)(rd); \ 65284194Sdelphij __asm __volatile("casa [%1] %2, %3, %0" \ 66284194Sdelphij : "+r" (__rd) : "r" (rs1), "n" (asi), "r" (rs2)); \ 67284194Sdelphij __rd; \ 68284194Sdelphij}) 69284194Sdelphij 70284194Sdelphij#define casxa(rs1, rs2, rd, asi) ({ \ 71284194Sdelphij u_long __rd = (u_int64_t)(rd); \ 72284194Sdelphij __asm __volatile("casxa [%1] %2, %3, %0" \ 73284194Sdelphij : "+r" (__rd) : "r" (rs1), "n" (asi), "r" (rs2)); \ 74284194Sdelphij __rd; \ 75284194Sdelphij}) 76284194Sdelphij 77284194Sdelphij#define flush(va) do { \ 78284194Sdelphij __asm __volatile("flush %0" : : "r" (va)); \ 79284194Sdelphij} while (0) 80284194Sdelphij 81284194Sdelphij#define flushw() do { \ 82284194Sdelphij __asm __volatile("flushw" : :); \ 83284194Sdelphij} while (0) 84284194Sdelphij 85284194Sdelphij#define mov(val, reg) do { \ 86284194Sdelphij __asm __volatile("mov %0, %" __XSTRING(reg) : : "r" (val)); \ 87284194Sdelphij} while (0) 88284194Sdelphij 89284194Sdelphij/* Generate ld*a/st*a functions for non-constant ASI's. */ 90284194Sdelphij#define LDNC_GEN(tp, o) \ 91284194Sdelphij static __inline tp \ 92284194Sdelphij o ## _nc(caddr_t va, int asi) \ 93284194Sdelphij { \ 94284194Sdelphij tp r; \ 95284194Sdelphij __asm __volatile("wr %2, 0, %%asi;" #o " [%1] %%asi, %0"\ 96284194Sdelphij : "=r" (r) : "r" (va), "r" (asi)); \ 97284194Sdelphij return (r); \ 98284194Sdelphij } 99284194Sdelphij 100284194SdelphijLDNC_GEN(u_char, lduba); 101284194SdelphijLDNC_GEN(u_short, lduha); 102284194SdelphijLDNC_GEN(u_int, lduwa); 103284194SdelphijLDNC_GEN(u_long, ldxa); 104284194Sdelphij 105284194Sdelphij#define LD_GENERIC(va, asi, op, type) ({ \ 106284194Sdelphij type __r; \ 107284194Sdelphij __asm __volatile(#op " [%1] %2, %0" \ 108284194Sdelphij : "=r" (__r) : "r" (va), "n" (asi)); \ 109284194Sdelphij __r; \ 110284194Sdelphij}) 111284194Sdelphij 112284194Sdelphij#define lduba(va, asi) LD_GENERIC(va, asi, lduba, u_char) 113284194Sdelphij#define lduha(va, asi) LD_GENERIC(va, asi, lduha, u_short) 114284194Sdelphij#define lduwa(va, asi) LD_GENERIC(va, asi, lduwa, u_int) 115284194Sdelphij#define ldxa(va, asi) LD_GENERIC(va, asi, ldxa, u_long) 116284194Sdelphij 117284194Sdelphij#define STNC_GEN(tp, o) \ 118284194Sdelphij static __inline void \ 119284194Sdelphij o ## _nc(caddr_t va, int asi, tp val) \ 120284194Sdelphij { \ 121284194Sdelphij __asm __volatile("wr %2, 0, %%asi;" #o " %0, [%1] %%asi"\ 122284194Sdelphij : : "r" (val), "r" (va), "r" (asi)); \ 123284194Sdelphij } 124284194Sdelphij 125284194SdelphijSTNC_GEN(u_char, stba); 126284194SdelphijSTNC_GEN(u_short, stha); 127284194SdelphijSTNC_GEN(u_int, stwa); 128284194SdelphijSTNC_GEN(u_long, stxa); 129284194Sdelphij 130284194Sdelphij#define ST_GENERIC(va, asi, val, op) \ 131284194Sdelphij __asm __volatile(#op " %0, [%1] %2" \ 132284194Sdelphij : : "r" (val), "r" (va), "n" (asi)); \ 133284194Sdelphij 134284194Sdelphij#define stba(va, asi, val) ST_GENERIC(va, asi, val, stba) 135284194Sdelphij#define stha(va, asi, val) ST_GENERIC(va, asi, val, stha) 136284194Sdelphij#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stwa) 137284194Sdelphij#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stxa) 138284194Sdelphij 139284194Sdelphij/* 140284194Sdelphij * Attempt to read from addr, val. If a Data Access Error trap happens, 141284194Sdelphij * they return -1 and the contents of val is undefined. A return of 0 142284194Sdelphij * means no trap happened, and the contents of val is valid. 143284194Sdelphij */ 144284194Sdelphijint fasword8(u_long asi, void *addr, uint8_t *val); 145284194Sdelphijint fasword16(u_long asi, void *addr, uint16_t *val); 146284194Sdelphijint fasword32(u_long asi, void *addr, uint32_t *val); 147284194Sdelphij 148284194Sdelphij#define membar(mask) do { \ 149284194Sdelphij __asm __volatile("membar %0" : : "n" (mask) : "memory"); \ 150284194Sdelphij} while (0) 151284194Sdelphij 152284194Sdelphij#define rd(name) ({ \ 153284194Sdelphij u_int64_t __sr; \ 154284194Sdelphij __asm __volatile("rd %%" #name ", %0" : "=r" (__sr) :); \ 155284194Sdelphij __sr; \ 156284194Sdelphij}) 157284194Sdelphij 158284194Sdelphij#define wr(name, val, xor) do { \ 159284194Sdelphij __asm __volatile("wr %0, %1, %%" #name \ 160284194Sdelphij : : "r" (val), "rI" (xor)); \ 161284194Sdelphij} while (0) 162284194Sdelphij 163284194Sdelphij#define rdpr(name) ({ \ 164284194Sdelphij u_int64_t __pr; \ 165284194Sdelphij __asm __volatile("rdpr %%" #name", %0" : "=r" (__pr) :); \ 166284194Sdelphij __pr; \ 167284194Sdelphij}) 168284194Sdelphij 169284194Sdelphij#define wrpr(name, val, xor) do { \ 170284194Sdelphij __asm __volatile("wrpr %0, %1, %%" #name \ 171284194Sdelphij : : "r" (val), "rI" (xor)); \ 172284194Sdelphij} while (0) 173284194Sdelphij 174284194Sdelphijstatic __inline void 175284194Sdelphijbreakpoint(void) 176284194Sdelphij{ 177284194Sdelphij __asm __volatile("ta %%xcc, 1" : :); 178284194Sdelphij} 179284194Sdelphij 180284194Sdelphijstatic __inline register_t 181284194Sdelphijintr_disable(void) 182284194Sdelphij{ 183284194Sdelphij u_long s; 184284194Sdelphij 185284194Sdelphij s = rdpr(pstate); 186284194Sdelphij wrpr(pstate, s & ~PSTATE_IE, 0); 187284194Sdelphij return (s); 188284194Sdelphij} 189284194Sdelphij#define intr_restore(s) wrpr(pstate, (s), 0) 190284194Sdelphij 191284194Sdelphij/* 192284194Sdelphij * In some places, it is required that the store is directly followed by a 193284194Sdelphij * membar #Sync. Don't trust the compiler to not insert instructions in 194284194Sdelphij * between. We also need to disable interrupts completely. 195284194Sdelphij */ 196284194Sdelphij#define stxa_sync(va, asi, val) do { \ 197284194Sdelphij u_long s = intr_disable(); \ 198284194Sdelphij __asm __volatile("stxa %0, [%1] %2; membar #Sync" \ 199284194Sdelphij : : "r" (val), "r" (va), "n" (asi)); \ 200284194Sdelphij intr_restore(s); \ 201284194Sdelphij} while (0) 202284194Sdelphij 203284194Sdelphijvoid ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len); 204284194Sdelphijvoid ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len); 205284194Sdelphijvoid ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len); 206284194Sdelphijvoid aszero(u_long asi, vm_offset_t dst, size_t len); 207284194Sdelphij 208284194Sdelphij/* 209284194Sdelphij * Ultrasparc II doesn't implement popc in hardware. Suck. 210284194Sdelphij */ 211284194Sdelphij#if 0 212284194Sdelphij#define HAVE_INLINE_FFS 213284194Sdelphij/* 214284194Sdelphij * See page 202 of the SPARC v9 Architecture Manual. 215284194Sdelphij */ 216284194Sdelphijstatic __inline int 217284194Sdelphijffs(int mask) 218284194Sdelphij{ 219284194Sdelphij int result; 220284194Sdelphij int neg; 221284194Sdelphij int tmp; 222284194Sdelphij 223284194Sdelphij __asm __volatile( 224284194Sdelphij " neg %3, %1 ; " 225284194Sdelphij " xnor %3, %1, %2 ; " 226284194Sdelphij " popc %2, %0 ; " 227284194Sdelphij " movrz %3, %%g0, %0 ; " 228284194Sdelphij : "=r" (result), "=r" (neg), "=r" (tmp) : "r" (mask)); 229284194Sdelphij return (result); 230284194Sdelphij} 231284194Sdelphij#endif 232284194Sdelphij 233284194Sdelphij#undef LDNC_GEN 234284194Sdelphij#undef STNC_GEN 235284194Sdelphij 236284194Sdelphij#endif /* !_MACHINE_CPUFUNC_H_ */ 237284194Sdelphij