10ec57554Sraf /* 20ec57554Sraf * CDDL HEADER START 30ec57554Sraf * 40ec57554Sraf * The contents of this file are subject to the terms of the 50ec57554Sraf * Common Development and Distribution License (the "License"). 60ec57554Sraf * You may not use this file except in compliance with the License. 70ec57554Sraf * 80ec57554Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90ec57554Sraf * or http://www.opensolaris.org/os/licensing. 100ec57554Sraf * See the License for the specific language governing permissions 110ec57554Sraf * and limitations under the License. 120ec57554Sraf * 130ec57554Sraf * When distributing Covered Code, include this CDDL HEADER in each 140ec57554Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150ec57554Sraf * If applicable, add the following below this CDDL HEADER, with the 160ec57554Sraf * fields enclosed by brackets "[]" replaced with your own identifying 170ec57554Sraf * information: Portions Copyright [yyyy] [name of copyright owner] 180ec57554Sraf * 190ec57554Sraf * CDDL HEADER END 200ec57554Sraf */ 210ec57554Sraf 220ec57554Sraf /* 23ae115bc7Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240ec57554Sraf * Use is subject to license terms. 250ec57554Sraf */ 260ec57554Sraf 270ec57554Sraf #ifndef _THR_INLINES_H 280ec57554Sraf #define _THR_INLINES_H 290ec57554Sraf 30*6a3e8e86SRichard Lowe #include <sys/ccompile.h> 310ec57554Sraf 320ec57554Sraf #if !defined(__lint) && defined(__GNUC__) 330ec57554Sraf 340ec57554Sraf /* inlines for gcc */ 350ec57554Sraf 36*6a3e8e86SRichard Lowe /* 37*6a3e8e86SRichard Lowe * ON-usable GCC 4.x emits register pseudo-ops declaring %g7 as ignored, rather 38*6a3e8e86SRichard Lowe * than scratch, GCC 3 does the reverse. All uses, both ones it generated 39*6a3e8e86SRichard Lowe * (_curthread) and ones it didn't (__curthread) must agree. 40*6a3e8e86SRichard Lowe */ 41*6a3e8e86SRichard Lowe #if __GNUC__ > 3 42*6a3e8e86SRichard Lowe #define SPARC_REG_SPEC "#ignore" 43*6a3e8e86SRichard Lowe #else 44*6a3e8e86SRichard Lowe #define SPARC_REG_SPEC "#scratch" 45*6a3e8e86SRichard Lowe #endif 46*6a3e8e86SRichard Lowe 47*6a3e8e86SRichard Lowe extern __GNU_INLINE ulwp_t * 480ec57554Sraf _curthread(void) 490ec57554Sraf { 500ec57554Sraf #if defined(__amd64) 510ec57554Sraf ulwp_t *__value; 520ec57554Sraf __asm__ __volatile__("movq %%fs:0, %0" : "=r" (__value)); 530ec57554Sraf #elif defined(__i386) 540ec57554Sraf ulwp_t *__value; 550ec57554Sraf __asm__ __volatile__("movl %%gs:0, %0" : "=r" (__value)); 560ec57554Sraf #elif defined(__sparc) 570ec57554Sraf register ulwp_t *__value __asm__("g7"); 580ec57554Sraf #else 590ec57554Sraf #error "port me" 600ec57554Sraf #endif 610ec57554Sraf return (__value); 620ec57554Sraf } 630ec57554Sraf 64*6a3e8e86SRichard Lowe extern __GNU_INLINE ulwp_t * 650ec57554Sraf __curthread(void) 660ec57554Sraf { 670ec57554Sraf ulwp_t *__value; 680ec57554Sraf __asm__ __volatile__( 690ec57554Sraf #if defined(__amd64) 700ec57554Sraf "movq %%fs:0, %0\n\t" 710ec57554Sraf #elif defined(__i386) 720ec57554Sraf "movl %%gs:0, %0\n\t" 730ec57554Sraf #elif defined(__sparcv9) 74*6a3e8e86SRichard Lowe ".register %%g7, " SPARC_REG_SPEC "\n\t" 750ec57554Sraf "ldx [%%g7 + 80], %0\n\t" 760ec57554Sraf #elif defined(__sparc) 77*6a3e8e86SRichard Lowe ".register %%g7, " SPARC_REG_SPEC "\n\t" 780ec57554Sraf "ld [%%g7 + 80], %0\n\t" 790ec57554Sraf #else 800ec57554Sraf #error "port me" 810ec57554Sraf #endif 82*6a3e8e86SRichard Lowe : "=r" (__value)); 830ec57554Sraf return (__value); 840ec57554Sraf } 850ec57554Sraf 86*6a3e8e86SRichard Lowe extern __GNU_INLINE greg_t 870ec57554Sraf stkptr(void) 880ec57554Sraf { 890ec57554Sraf #if defined(__amd64) 900ec57554Sraf register greg_t __value __asm__("rsp"); 910ec57554Sraf #elif defined(__i386) 920ec57554Sraf register greg_t __value __asm__("esp"); 930ec57554Sraf #elif defined(__sparc) 940ec57554Sraf register greg_t __value __asm__("sp"); 950ec57554Sraf #else 960ec57554Sraf #error "port me" 970ec57554Sraf #endif 980ec57554Sraf return (__value); 990ec57554Sraf } 1000ec57554Sraf 101*6a3e8e86SRichard Lowe extern __GNU_INLINE hrtime_t 1020ec57554Sraf gethrtime(void) /* note: caller-saved registers are trashed */ 1030ec57554Sraf { 1040ec57554Sraf #if defined(__amd64) 1050ec57554Sraf hrtime_t __value; 1060ec57554Sraf __asm__ __volatile__( 1070ec57554Sraf "movl $3, %%eax\n\t" 1080ec57554Sraf "int $0xd2" 1090ec57554Sraf : "=a" (__value) 1100ec57554Sraf : : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "cc"); 1110ec57554Sraf #elif defined(__i386) 1120ec57554Sraf hrtime_t __value; 1130ec57554Sraf __asm__ __volatile__( 1140ec57554Sraf "movl $3, %%eax\n\t" 1150ec57554Sraf "int $0xd2" 1160ec57554Sraf : "=A" (__value) 1170ec57554Sraf : : "ecx", "cc"); 1180ec57554Sraf #elif defined(__sparcv9) 1190ec57554Sraf register hrtime_t __value __asm__("o0"); 1200ec57554Sraf __asm__ __volatile__( 1210ec57554Sraf "ta 0x24\n\t" 1220ec57554Sraf "sllx %%o0, 32, %0\n\t" 1230ec57554Sraf "or %%o1, %0, %0" 1240ec57554Sraf : "=r" (__value) 1250ec57554Sraf : : "o1", "o2", "o3", "o4", "o5", "cc"); 1260ec57554Sraf #elif defined(__sparc) 1270ec57554Sraf register hrtime_t __value __asm__("o0"); 1280ec57554Sraf __asm__ __volatile__( 1290ec57554Sraf "ta 0x24" 1300ec57554Sraf : "=r" (__value) 1310ec57554Sraf : : "o2", "o3", "o4", "o5", "cc"); 1320ec57554Sraf #else 1330ec57554Sraf #error "port me" 1340ec57554Sraf #endif 1350ec57554Sraf return (__value); 1360ec57554Sraf } 1370ec57554Sraf 138*6a3e8e86SRichard Lowe extern __GNU_INLINE int 1390ec57554Sraf set_lock_byte(volatile uint8_t *__lockp) 1400ec57554Sraf { 1410ec57554Sraf int __value; 1420ec57554Sraf #if defined(__x86) 1430ec57554Sraf __asm__ __volatile__( 1440ec57554Sraf "movl $1, %0\n\t" 1450ec57554Sraf "xchgb %%dl, %1" 1460ec57554Sraf : "+d" (__value), "+m" (*__lockp)); 1470ec57554Sraf #elif defined(__sparc) 1480ec57554Sraf __asm__ __volatile__( 1490ec57554Sraf "ldstub %1, %0\n\t" 1500ec57554Sraf "membar #LoadLoad" 1510ec57554Sraf : "=r" (__value), "+m" (*__lockp)); 1520ec57554Sraf #else 1530ec57554Sraf #error "port me" 1540ec57554Sraf #endif 1550ec57554Sraf return (__value); 1560ec57554Sraf } 1570ec57554Sraf 158*6a3e8e86SRichard Lowe extern __GNU_INLINE uint32_t 15941efec22Sraf atomic_swap_32(volatile uint32_t *__memory, uint32_t __value) 1600ec57554Sraf { 1610ec57554Sraf #if defined(__x86) 1620ec57554Sraf __asm__ __volatile__( 1630ec57554Sraf "xchgl %0, %1" 1640ec57554Sraf : "+q" (__value), "+m" (*__memory)); 1650ec57554Sraf return (__value); 1660ec57554Sraf #elif defined(__sparc) 1670ec57554Sraf uint32_t __tmp1, __tmp2; 1680ec57554Sraf __asm__ __volatile__( 1690ec57554Sraf "ld [%3], %0\n\t" 1700ec57554Sraf "1:\n\t" 1710ec57554Sraf "mov %4, %1\n\t" 1720ec57554Sraf "cas [%3], %0, %1\n\t" 1730ec57554Sraf "cmp %0, %1\n\t" 1740ec57554Sraf "bne,a,pn %%icc, 1b\n\t" 1750ec57554Sraf " mov %1, %0" 1760ec57554Sraf : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 1770ec57554Sraf : "r" (__memory), "r" (__value) 1780ec57554Sraf : "cc"); 1790ec57554Sraf return (__tmp2); 1800ec57554Sraf #else 1810ec57554Sraf #error "port me" 1820ec57554Sraf #endif 1830ec57554Sraf } 1840ec57554Sraf 185*6a3e8e86SRichard Lowe extern __GNU_INLINE uint32_t 18641efec22Sraf atomic_cas_32(volatile uint32_t *__memory, uint32_t __cmp, uint32_t __newvalue) 1870ec57554Sraf { 1880ec57554Sraf uint32_t __oldvalue; 1890ec57554Sraf #if defined(__x86) 1900ec57554Sraf __asm__ __volatile__( 1910ec57554Sraf "lock; cmpxchgl %3, %0" 1920ec57554Sraf : "=m" (*__memory), "=a" (__oldvalue) 1930ec57554Sraf : "a" (__cmp), "r" (__newvalue)); 1940ec57554Sraf #elif defined(__sparc) 1950ec57554Sraf __asm__ __volatile__( 1960ec57554Sraf "cas [%2], %3, %1" 19741efec22Sraf : "=m" (*__memory), "=&r" (__oldvalue) 1980ec57554Sraf : "r" (__memory), "r" (__cmp), "1" (__newvalue)); 1990ec57554Sraf #else 2000ec57554Sraf #error "port me" 2010ec57554Sraf #endif 2020ec57554Sraf return (__oldvalue); 2030ec57554Sraf } 2040ec57554Sraf 205*6a3e8e86SRichard Lowe extern __GNU_INLINE void 20641efec22Sraf atomic_inc_32(volatile uint32_t *__memory) 2070ec57554Sraf { 2080ec57554Sraf #if defined(__x86) 2090ec57554Sraf __asm__ __volatile__( 2100ec57554Sraf "lock; incl %0" 2110ec57554Sraf : "+m" (*__memory)); 2120ec57554Sraf #elif defined(__sparc) 2130ec57554Sraf uint32_t __tmp1, __tmp2; 2140ec57554Sraf __asm__ __volatile__( 2150ec57554Sraf "ld [%3], %0\n\t" 2160ec57554Sraf "1:\n\t" 2170ec57554Sraf "add %0, 1, %1\n\t" 2180ec57554Sraf "cas [%3], %0, %1\n\t" 2190ec57554Sraf "cmp %0, %1\n\t" 2200ec57554Sraf "bne,a,pn %%icc, 1b\n\t" 2210ec57554Sraf " mov %1, %0" 2220ec57554Sraf : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 2230ec57554Sraf : "r" (__memory) 2240ec57554Sraf : "cc"); 2250ec57554Sraf #else 2260ec57554Sraf #error "port me" 2270ec57554Sraf #endif 2280ec57554Sraf } 2290ec57554Sraf 230*6a3e8e86SRichard Lowe extern __GNU_INLINE void 23141efec22Sraf atomic_dec_32(volatile uint32_t *__memory) 2320ec57554Sraf { 2330ec57554Sraf #if defined(__x86) 2340ec57554Sraf __asm__ __volatile__( 2350ec57554Sraf "lock; decl %0" 2360ec57554Sraf : "+m" (*__memory)); 2370ec57554Sraf #elif defined(__sparc) 2380ec57554Sraf uint32_t __tmp1, __tmp2; 2390ec57554Sraf __asm__ __volatile__( 2400ec57554Sraf "ld [%3], %0\n\t" 2410ec57554Sraf "1:\n\t" 2420ec57554Sraf "sub %0, 1, %1\n\t" 2430ec57554Sraf "cas [%3], %0, %1\n\t" 2440ec57554Sraf "cmp %0, %1\n\t" 2450ec57554Sraf "bne,a,pn %%icc, 1b\n\t" 2460ec57554Sraf " mov %1, %0" 2470ec57554Sraf : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 2480ec57554Sraf : "r" (__memory) 2490ec57554Sraf : "cc"); 2500ec57554Sraf #else 2510ec57554Sraf #error "port me" 2520ec57554Sraf #endif 2530ec57554Sraf } 2540ec57554Sraf 255*6a3e8e86SRichard Lowe extern __GNU_INLINE void 25641efec22Sraf atomic_and_32(volatile uint32_t *__memory, uint32_t __bits) 25741efec22Sraf { 25841efec22Sraf #if defined(__x86) 25941efec22Sraf __asm__ __volatile__( 26041efec22Sraf "lock; andl %1, %0" 26141efec22Sraf : "+m" (*__memory) 26241efec22Sraf : "r" (__bits)); 26341efec22Sraf #elif defined(__sparc) 26441efec22Sraf uint32_t __tmp1, __tmp2; 26541efec22Sraf __asm__ __volatile__( 26641efec22Sraf "ld [%3], %0\n\t" 26741efec22Sraf "1:\n\t" 26841efec22Sraf "and %0, %4, %1\n\t" 26941efec22Sraf "cas [%3], %0, %1\n\t" 27041efec22Sraf "cmp %0, %1\n\t" 27141efec22Sraf "bne,a,pn %%icc, 1b\n\t" 27241efec22Sraf " mov %1, %0" 27341efec22Sraf : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 27441efec22Sraf : "r" (__memory), "r" (__bits) 27541efec22Sraf : "cc"); 27641efec22Sraf #else 27741efec22Sraf #error "port me" 27841efec22Sraf #endif 27941efec22Sraf } 28041efec22Sraf 281*6a3e8e86SRichard Lowe extern __GNU_INLINE void 28241efec22Sraf atomic_or_32(volatile uint32_t *__memory, uint32_t __bits) 28341efec22Sraf { 28441efec22Sraf #if defined(__x86) 28541efec22Sraf __asm__ __volatile__( 28641efec22Sraf "lock; orl %1, %0" 28741efec22Sraf : "+m" (*__memory) 28841efec22Sraf : "r" (__bits)); 28941efec22Sraf #elif defined(__sparc) 29041efec22Sraf uint32_t __tmp1, __tmp2; 29141efec22Sraf __asm__ __volatile__( 29241efec22Sraf "ld [%3], %0\n\t" 29341efec22Sraf "1:\n\t" 29441efec22Sraf "or %0, %4, %1\n\t" 29541efec22Sraf "cas [%3], %0, %1\n\t" 29641efec22Sraf "cmp %0, %1\n\t" 29741efec22Sraf "bne,a,pn %%icc, 1b\n\t" 29841efec22Sraf " mov %1, %0" 29941efec22Sraf : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 30041efec22Sraf : "r" (__memory), "r" (__bits) 30141efec22Sraf : "cc"); 30241efec22Sraf #else 30341efec22Sraf #error "port me" 30441efec22Sraf #endif 30541efec22Sraf } 30641efec22Sraf 3070ec57554Sraf #if defined(__sparc) /* only needed on sparc */ 3080ec57554Sraf 309*6a3e8e86SRichard Lowe extern __GNU_INLINE ulong_t 3100ec57554Sraf caller(void) 3110ec57554Sraf { 3120ec57554Sraf register ulong_t __value __asm__("i7"); 3130ec57554Sraf return (__value); 3140ec57554Sraf } 3150ec57554Sraf 316*6a3e8e86SRichard Lowe extern __GNU_INLINE ulong_t 3170ec57554Sraf getfp(void) 3180ec57554Sraf { 3190ec57554Sraf register ulong_t __value __asm__("fp"); 3200ec57554Sraf return (__value); 3210ec57554Sraf } 3220ec57554Sraf 3230ec57554Sraf #endif /* __sparc */ 3240ec57554Sraf 3250ec57554Sraf #if defined(__x86) /* only needed on x86 */ 3260ec57554Sraf 327*6a3e8e86SRichard Lowe extern __GNU_INLINE void 3280ec57554Sraf ht_pause(void) 3290ec57554Sraf { 3300ec57554Sraf __asm__ __volatile__("rep; nop"); 3310ec57554Sraf } 3320ec57554Sraf 3330ec57554Sraf #endif /* __x86 */ 3340ec57554Sraf 3350ec57554Sraf #endif /* !__lint && __GNUC__ */ 3360ec57554Sraf 3370ec57554Sraf #endif /* _THR_INLINES_H */ 338