cpufunc.h revision 216972
1178172Simp/* $OpenBSD: pio.h,v 1.2 1998/09/15 10:50:12 pefo Exp $ */ 2178172Simp 3206713Sjmallett/*- 4206713Sjmallett * Copyright (c) 2002-2004 Juli Mallett. All rights reserved. 5206713Sjmallett * 6206713Sjmallett * Redistribution and use in source and binary forms, with or without 7206713Sjmallett * modification, are permitted provided that the following conditions 8206713Sjmallett * are met: 9206713Sjmallett * 1. Redistributions of source code must retain the above copyright 10206713Sjmallett * notice, this list of conditions and the following disclaimer. 11206713Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 12206713Sjmallett * notice, this list of conditions and the following disclaimer in the 13206713Sjmallett * documentation and/or other materials provided with the distribution. 14206713Sjmallett * 15206713Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16206713Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17206713Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18206713Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19206713Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20206713Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21206713Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22206713Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23206713Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24206713Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25206713Sjmallett * SUCH DAMAGE. 26206713Sjmallett */ 27178172Simp/* 28178172Simp * Copyright (c) 1995-1999 Per Fogelstrom. All rights reserved. 29178172Simp * 30178172Simp * Redistribution and use in source and binary forms, with or without 31178172Simp * modification, are permitted provided that the following conditions 32178172Simp * are met: 33178172Simp * 1. Redistributions of source code must retain the above copyright 34178172Simp * notice, this list of conditions and the following disclaimer. 35178172Simp * 2. Redistributions in binary form must reproduce the above copyright 36178172Simp * notice, this list of conditions and the following disclaimer in the 37178172Simp * documentation and/or other materials provided with the distribution. 38178172Simp * 3. All advertising materials mentioning features or use of this software 39178172Simp * must display the following acknowledgement: 40178172Simp * This product includes software developed by Per Fogelstrom. 41178172Simp * 4. The name of the author may not be used to endorse or promote products 42178172Simp * derived from this software without specific prior written permission 43178172Simp * 44178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 45178172Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46178172Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47178172Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 48178172Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 49178172Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 50178172Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 51178172Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52178172Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 53178172Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54178172Simp * 55178172Simp * JNPR: cpufunc.h,v 1.5 2007/08/09 11:23:32 katta 56178172Simp * $FreeBSD: head/sys/mips/include/cpufunc.h 216972 2011-01-04 19:32:03Z jmallett $ 57178172Simp */ 58178172Simp 59178172Simp#ifndef _MACHINE_CPUFUNC_H_ 60178172Simp#define _MACHINE_CPUFUNC_H_ 61178172Simp 62178172Simp#include <sys/types.h> 63178172Simp#include <machine/cpuregs.h> 64178172Simp 65178172Simp/* 66178172Simp * These functions are required by user-land atomi ops 67178172Simp */ 68178172Simp 69178172Simpstatic __inline void 70178172Simpmips_barrier(void) 71178172Simp{ 72178172Simp __asm __volatile (".set noreorder\n\t" 73178172Simp "nop\n\t" 74178172Simp "nop\n\t" 75178172Simp "nop\n\t" 76178172Simp "nop\n\t" 77178172Simp "nop\n\t" 78178172Simp "nop\n\t" 79178172Simp "nop\n\t" 80178172Simp "nop\n\t" 81178172Simp ".set reorder\n\t" 82178172Simp : : : "memory"); 83178172Simp} 84178172Simp 85178172Simpstatic __inline void 86206713Sjmallettmips_cp0_sync(void) 87206713Sjmallett{ 88206713Sjmallett __asm __volatile (__XSTRING(COP0_SYNC)); 89206713Sjmallett} 90206713Sjmallett 91206713Sjmallettstatic __inline void 92178172Simpmips_wbflush(void) 93178172Simp{ 94178172Simp __asm __volatile ("sync" : : : "memory"); 95178172Simp mips_barrier(); 96178172Simp} 97178172Simp 98178172Simpstatic __inline void 99178172Simpmips_read_membar(void) 100178172Simp{ 101178172Simp /* Nil */ 102178172Simp} 103178172Simp 104178172Simpstatic __inline void 105178172Simpmips_write_membar(void) 106178172Simp{ 107178172Simp mips_wbflush(); 108178172Simp} 109178172Simp 110178172Simp#ifdef _KERNEL 111216947Sjmallett/* 112216947Sjmallett * XXX 113216947Sjmallett * It would be nice to add variants that read/write register_t, to avoid some 114216947Sjmallett * ABI checks. 115216947Sjmallett */ 116206713Sjmallett#if defined(__mips_n32) || defined(__mips_n64) 117216972Sjmallett#define MIPS_RW64_COP0(n,r) \ 118178172Simpstatic __inline uint64_t \ 119178172Simpmips_rd_ ## n (void) \ 120178172Simp{ \ 121178172Simp int v0; \ 122178172Simp __asm __volatile ("dmfc0 %[v0], $"__XSTRING(r)";" \ 123178172Simp : [v0] "=&r"(v0)); \ 124178172Simp mips_barrier(); \ 125178172Simp return (v0); \ 126178172Simp} \ 127178172Simpstatic __inline void \ 128178172Simpmips_wr_ ## n (uint64_t a0) \ 129178172Simp{ \ 130178172Simp __asm __volatile ("dmtc0 %[a0], $"__XSTRING(r)";" \ 131178172Simp __XSTRING(COP0_SYNC)";" \ 132178172Simp "nop;" \ 133178172Simp "nop;" \ 134178172Simp : \ 135178172Simp : [a0] "r"(a0)); \ 136178172Simp mips_barrier(); \ 137178172Simp} struct __hack 138178172Simp 139206713Sjmallett#if defined(__mips_n64) 140216972SjmallettMIPS_RW64_COP0(excpc, MIPS_COP_0_EXC_PC); 141216972SjmallettMIPS_RW64_COP0(entrylo0, MIPS_COP_0_TLB_LO0); 142216972SjmallettMIPS_RW64_COP0(entrylo1, MIPS_COP_0_TLB_LO1); 143216972SjmallettMIPS_RW64_COP0(entryhi, MIPS_COP_0_TLB_HI); 144216972SjmallettMIPS_RW64_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK); 145206713Sjmallett#endif 146216972SjmallettMIPS_RW64_COP0(xcontext, MIPS_COP_0_TLB_XCONTEXT); 147178172Simp 148216972Sjmallett#undef MIPS_RW64_COP0 149178172Simp#endif 150178172Simp 151216972Sjmallett#define MIPS_RW32_COP0(n,r) \ 152178172Simpstatic __inline uint32_t \ 153178172Simpmips_rd_ ## n (void) \ 154178172Simp{ \ 155178172Simp int v0; \ 156178172Simp __asm __volatile ("mfc0 %[v0], $"__XSTRING(r)";" \ 157178172Simp : [v0] "=&r"(v0)); \ 158178172Simp mips_barrier(); \ 159178172Simp return (v0); \ 160178172Simp} \ 161178172Simpstatic __inline void \ 162178172Simpmips_wr_ ## n (uint32_t a0) \ 163178172Simp{ \ 164178172Simp __asm __volatile ("mtc0 %[a0], $"__XSTRING(r)";" \ 165178172Simp __XSTRING(COP0_SYNC)";" \ 166178172Simp "nop;" \ 167178172Simp "nop;" \ 168178172Simp : \ 169178172Simp : [a0] "r"(a0)); \ 170178172Simp mips_barrier(); \ 171178172Simp} struct __hack 172178172Simp 173216972Sjmallett#define MIPS_RW32_COP0_SEL(n,r,s) \ 174202031Simpstatic __inline uint32_t \ 175206829Sjmallettmips_rd_ ## n(void) \ 176202031Simp{ \ 177202031Simp int v0; \ 178202031Simp __asm __volatile ("mfc0 %[v0], $"__XSTRING(r)", "__XSTRING(s)";" \ 179202031Simp : [v0] "=&r"(v0)); \ 180202031Simp mips_barrier(); \ 181202031Simp return (v0); \ 182202031Simp} \ 183202031Simpstatic __inline void \ 184206829Sjmallettmips_wr_ ## n(uint32_t a0) \ 185202031Simp{ \ 186202031Simp __asm __volatile ("mtc0 %[a0], $"__XSTRING(r)", "__XSTRING(s)";" \ 187202031Simp __XSTRING(COP0_SYNC)";" \ 188202031Simp "nop;" \ 189202031Simp "nop;" \ 190202031Simp : \ 191202031Simp : [a0] "r"(a0)); \ 192202031Simp mips_barrier(); \ 193202031Simp} struct __hack 194202031Simp 195210311Sjmallett#ifdef CPU_CNMIPS 196178172Simpstatic __inline void mips_sync_icache (void) 197178172Simp{ 198202031Simp __asm __volatile ( 199202031Simp ".set push\n" 200202031Simp ".set mips64\n" 201202031Simp ".word 0x041f0000\n" /* xxx ICACHE */ 202202031Simp "nop\n" 203202031Simp ".set pop\n" 204202031Simp : : ); 205178172Simp} 206178172Simp#endif 207178172Simp 208216972SjmallettMIPS_RW32_COP0(compare, MIPS_COP_0_COMPARE); 209216972SjmallettMIPS_RW32_COP0(config, MIPS_COP_0_CONFIG); 210216972SjmallettMIPS_RW32_COP0_SEL(config1, MIPS_COP_0_CONFIG, 1); 211216972SjmallettMIPS_RW32_COP0_SEL(config2, MIPS_COP_0_CONFIG, 2); 212216972SjmallettMIPS_RW32_COP0_SEL(config3, MIPS_COP_0_CONFIG, 3); 213216972SjmallettMIPS_RW32_COP0(count, MIPS_COP_0_COUNT); 214216972SjmallettMIPS_RW32_COP0(index, MIPS_COP_0_TLB_INDEX); 215216972SjmallettMIPS_RW32_COP0(wired, MIPS_COP_0_TLB_WIRED); 216216972SjmallettMIPS_RW32_COP0(cause, MIPS_COP_0_CAUSE); 217216947Sjmallett#if !defined(__mips_n64) 218216972SjmallettMIPS_RW32_COP0(excpc, MIPS_COP_0_EXC_PC); 219216947Sjmallett#endif 220216972SjmallettMIPS_RW32_COP0(status, MIPS_COP_0_STATUS); 221178172Simp 222178172Simp/* XXX: Some of these registers are specific to MIPS32. */ 223206713Sjmallett#if !defined(__mips_n64) 224216972SjmallettMIPS_RW32_COP0(entrylo0, MIPS_COP_0_TLB_LO0); 225216972SjmallettMIPS_RW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1); 226216972SjmallettMIPS_RW32_COP0(entryhi, MIPS_COP_0_TLB_HI); 227216972SjmallettMIPS_RW32_COP0(pagemask, MIPS_COP_0_TLB_PG_MASK); 228206713Sjmallett#endif 229216972SjmallettMIPS_RW32_COP0(prid, MIPS_COP_0_PRID); 230206713Sjmallett/* XXX 64-bit? */ 231216972SjmallettMIPS_RW32_COP0_SEL(ebase, MIPS_COP_0_PRID, 1); 232216972SjmallettMIPS_RW32_COP0(watchlo, MIPS_COP_0_WATCH_LO); 233216972SjmallettMIPS_RW32_COP0_SEL(watchlo1, MIPS_COP_0_WATCH_LO, 1); 234216972SjmallettMIPS_RW32_COP0_SEL(watchlo2, MIPS_COP_0_WATCH_LO, 2); 235216972SjmallettMIPS_RW32_COP0_SEL(watchlo3, MIPS_COP_0_WATCH_LO, 3); 236216972SjmallettMIPS_RW32_COP0(watchhi, MIPS_COP_0_WATCH_HI); 237216972SjmallettMIPS_RW32_COP0_SEL(watchhi1, MIPS_COP_0_WATCH_HI, 1); 238216972SjmallettMIPS_RW32_COP0_SEL(watchhi2, MIPS_COP_0_WATCH_HI, 2); 239216972SjmallettMIPS_RW32_COP0_SEL(watchhi3, MIPS_COP_0_WATCH_HI, 3); 240204635Sgnn 241216972SjmallettMIPS_RW32_COP0_SEL(perfcnt0, MIPS_COP_0_PERFCNT, 0); 242216972SjmallettMIPS_RW32_COP0_SEL(perfcnt1, MIPS_COP_0_PERFCNT, 1); 243216972SjmallettMIPS_RW32_COP0_SEL(perfcnt2, MIPS_COP_0_PERFCNT, 2); 244216972SjmallettMIPS_RW32_COP0_SEL(perfcnt3, MIPS_COP_0_PERFCNT, 3); 245204635Sgnn 246216972Sjmallett#undef MIPS_RW32_COP0 247216972Sjmallett#undef MIPS_RW32_COP0_SEL 248178172Simp 249178172Simpstatic __inline register_t 250178172Simpintr_disable(void) 251178172Simp{ 252178172Simp register_t s; 253178172Simp 254178172Simp s = mips_rd_status(); 255178172Simp mips_wr_status(s & ~MIPS_SR_INT_IE); 256178172Simp 257206713Sjmallett return (s & MIPS_SR_INT_IE); 258178172Simp} 259178172Simp 260178172Simpstatic __inline register_t 261178172Simpintr_enable(void) 262178172Simp{ 263178172Simp register_t s; 264178172Simp 265178172Simp s = mips_rd_status(); 266178172Simp mips_wr_status(s | MIPS_SR_INT_IE); 267178172Simp 268178172Simp return (s); 269178172Simp} 270178172Simp 271206713Sjmallettstatic __inline void 272206713Sjmallettintr_restore(register_t ie) 273206713Sjmallett{ 274206713Sjmallett if (ie == MIPS_SR_INT_IE) { 275206713Sjmallett intr_enable(); 276206713Sjmallett } 277206713Sjmallett} 278178172Simp 279212532Sjchandrastatic __inline uint32_t 280212532Sjchandraset_intr_mask(uint32_t mask) 281212532Sjchandra{ 282212532Sjchandra uint32_t ostatus; 283212532Sjchandra 284212532Sjchandra ostatus = mips_rd_status(); 285212632Sneel mask = (ostatus & ~MIPS_SR_INT_MASK) | (mask & MIPS_SR_INT_MASK); 286212532Sjchandra mips_wr_status(mask); 287212532Sjchandra return (ostatus); 288212532Sjchandra} 289212532Sjchandra 290212532Sjchandrastatic __inline uint32_t 291212532Sjchandraget_intr_mask(void) 292212532Sjchandra{ 293212532Sjchandra 294212532Sjchandra return (mips_rd_status() & MIPS_SR_INT_MASK); 295212532Sjchandra} 296212532Sjchandra 297178172Simpstatic __inline void 298178172Simpbreakpoint(void) 299178172Simp{ 300178172Simp __asm __volatile ("break"); 301178172Simp} 302178172Simp 303205675Sneel#if defined(__GNUC__) && !defined(__mips_o32) 304205675Sneelstatic inline uint64_t 305205675Sneelmips3_ld(const volatile uint64_t *va) 306205675Sneel{ 307205675Sneel uint64_t rv; 308205675Sneel 309205675Sneel#if defined(_LP64) 310205675Sneel rv = *va; 311205675Sneel#else 312205675Sneel __asm volatile("ld %0,0(%1)" : "=d"(rv) : "r"(va)); 313205675Sneel#endif 314205675Sneel 315205675Sneel return (rv); 316205675Sneel} 317205675Sneel 318205675Sneelstatic inline void 319205675Sneelmips3_sd(volatile uint64_t *va, uint64_t v) 320205675Sneel{ 321205675Sneel#if defined(_LP64) 322205675Sneel *va = v; 323205675Sneel#else 324205675Sneel __asm volatile("sd %0,0(%1)" :: "r"(v), "r"(va)); 325205675Sneel#endif 326205675Sneel} 327205675Sneel#else 328205675Sneeluint64_t mips3_ld(volatile uint64_t *va); 329205675Sneelvoid mips3_sd(volatile uint64_t *, uint64_t); 330205675Sneel#endif /* __GNUC__ */ 331205675Sneel 332178172Simp#endif /* _KERNEL */ 333178172Simp 334178172Simp#define readb(va) (*(volatile uint8_t *) (va)) 335178172Simp#define readw(va) (*(volatile uint16_t *) (va)) 336178172Simp#define readl(va) (*(volatile uint32_t *) (va)) 337178172Simp 338178172Simp#define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) 339178172Simp#define writew(va, d) (*(volatile uint16_t *) (va) = (d)) 340178172Simp#define writel(va, d) (*(volatile uint32_t *) (va) = (d)) 341178172Simp 342178172Simp/* 343178172Simp * I/O macros. 344178172Simp */ 345178172Simp 346178172Simp#define outb(a,v) (*(volatile unsigned char*)(a) = (v)) 347178172Simp#define out8(a,v) (*(volatile unsigned char*)(a) = (v)) 348178172Simp#define outw(a,v) (*(volatile unsigned short*)(a) = (v)) 349178172Simp#define out16(a,v) outw(a,v) 350178172Simp#define outl(a,v) (*(volatile unsigned int*)(a) = (v)) 351178172Simp#define out32(a,v) outl(a,v) 352178172Simp#define inb(a) (*(volatile unsigned char*)(a)) 353178172Simp#define in8(a) (*(volatile unsigned char*)(a)) 354178172Simp#define inw(a) (*(volatile unsigned short*)(a)) 355178172Simp#define in16(a) inw(a) 356178172Simp#define inl(a) (*(volatile unsigned int*)(a)) 357178172Simp#define in32(a) inl(a) 358178172Simp 359178172Simp#define out8rb(a,v) (*(volatile unsigned char*)(a) = (v)) 360178172Simp#define out16rb(a,v) (__out16rb((volatile uint16_t *)(a), v)) 361178172Simp#define out32rb(a,v) (__out32rb((volatile uint32_t *)(a), v)) 362178172Simp#define in8rb(a) (*(volatile unsigned char*)(a)) 363178172Simp#define in16rb(a) (__in16rb((volatile uint16_t *)(a))) 364178172Simp#define in32rb(a) (__in32rb((volatile uint32_t *)(a))) 365178172Simp 366178172Simp#define _swap_(x) (((x) >> 24) | ((x) << 24) | \ 367178172Simp (((x) >> 8) & 0xff00) | (((x) & 0xff00) << 8)) 368178172Simp 369178172Simpstatic __inline void __out32rb(volatile uint32_t *, uint32_t); 370178172Simpstatic __inline void __out16rb(volatile uint16_t *, uint16_t); 371178172Simpstatic __inline uint32_t __in32rb(volatile uint32_t *); 372178172Simpstatic __inline uint16_t __in16rb(volatile uint16_t *); 373178172Simp 374178172Simpstatic __inline void 375178172Simp__out32rb(volatile uint32_t *a, uint32_t v) 376178172Simp{ 377178172Simp uint32_t _v_ = v; 378178172Simp 379178172Simp _v_ = _swap_(_v_); 380178172Simp out32(a, _v_); 381178172Simp} 382178172Simp 383178172Simpstatic __inline void 384178172Simp__out16rb(volatile uint16_t *a, uint16_t v) 385178172Simp{ 386178172Simp uint16_t _v_; 387178172Simp 388178172Simp _v_ = ((v >> 8) & 0xff) | (v << 8); 389178172Simp out16(a, _v_); 390178172Simp} 391178172Simp 392178172Simpstatic __inline uint32_t 393178172Simp__in32rb(volatile uint32_t *a) 394178172Simp{ 395178172Simp uint32_t _v_; 396178172Simp 397178172Simp _v_ = in32(a); 398178172Simp _v_ = _swap_(_v_); 399178172Simp return _v_; 400178172Simp} 401178172Simp 402178172Simpstatic __inline uint16_t 403178172Simp__in16rb(volatile uint16_t *a) 404178172Simp{ 405178172Simp uint16_t _v_; 406178172Simp 407178172Simp _v_ = in16(a); 408178172Simp _v_ = ((_v_ >> 8) & 0xff) | (_v_ << 8); 409178172Simp return _v_; 410178172Simp} 411178172Simp 412178172Simpvoid insb(uint8_t *, uint8_t *,int); 413178172Simpvoid insw(uint16_t *, uint16_t *,int); 414178172Simpvoid insl(uint32_t *, uint32_t *,int); 415178172Simpvoid outsb(uint8_t *, const uint8_t *,int); 416178172Simpvoid outsw(uint16_t *, const uint16_t *,int); 417178172Simpvoid outsl(uint32_t *, const uint32_t *,int); 418178172Simpu_int loadandclear(volatile u_int *addr); 419178172Simp 420178172Simp#endif /* !_MACHINE_CPUFUNC_H_ */ 421