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 *
_curthread(void)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 *
__curthread(void)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
stkptr(void)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
gethrtime(void)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
set_lock_byte(volatile uint8_t * __lockp)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
atomic_swap_32(volatile uint32_t * __memory,uint32_t __value)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
atomic_cas_32(volatile uint32_t * __memory,uint32_t __cmp,uint32_t __newvalue)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
atomic_inc_32(volatile uint32_t * __memory)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
atomic_dec_32(volatile uint32_t * __memory)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
atomic_and_32(volatile uint32_t * __memory,uint32_t __bits)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
atomic_or_32(volatile uint32_t * __memory,uint32_t __bits)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
caller(void)3100ec57554Sraf caller(void)
3110ec57554Sraf {
3120ec57554Sraf register ulong_t __value __asm__("i7");
3130ec57554Sraf return (__value);
3140ec57554Sraf }
3150ec57554Sraf
316*6a3e8e86SRichard Lowe extern __GNU_INLINE ulong_t
getfp(void)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
ht_pause(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