xref: /freebsd/sys/amd64/include/cpufunc.h (revision e085f869d5c6ce0f8ea4ada858eac4b7ec2176ea)
13c4dd356SDavid Greenman /*-
2fcfe57d6SPeter Wemm  * Copyright (c) 2003 Peter Wemm.
33c4dd356SDavid Greenman  * Copyright (c) 1993 The Regents of the University of California.
43c4dd356SDavid Greenman  * All rights reserved.
53c4dd356SDavid Greenman  *
63c4dd356SDavid Greenman  * Redistribution and use in source and binary forms, with or without
73c4dd356SDavid Greenman  * modification, are permitted provided that the following conditions
83c4dd356SDavid Greenman  * are met:
93c4dd356SDavid Greenman  * 1. Redistributions of source code must retain the above copyright
103c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer.
113c4dd356SDavid Greenman  * 2. Redistributions in binary form must reproduce the above copyright
123c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer in the
133c4dd356SDavid Greenman  *    documentation and/or other materials provided with the distribution.
143c4dd356SDavid Greenman  * 4. Neither the name of the University nor the names of its contributors
153c4dd356SDavid Greenman  *    may be used to endorse or promote products derived from this software
163c4dd356SDavid Greenman  *    without specific prior written permission.
173c4dd356SDavid Greenman  *
183c4dd356SDavid Greenman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
193c4dd356SDavid Greenman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
203c4dd356SDavid Greenman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
213c4dd356SDavid Greenman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
223c4dd356SDavid Greenman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
233c4dd356SDavid Greenman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
243c4dd356SDavid Greenman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
253c4dd356SDavid Greenman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263c4dd356SDavid Greenman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
273c4dd356SDavid Greenman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
283c4dd356SDavid Greenman  * SUCH DAMAGE.
293c4dd356SDavid Greenman  *
30c3aac50fSPeter Wemm  * $FreeBSD$
313c4dd356SDavid Greenman  */
323c4dd356SDavid Greenman 
335b81b6b3SRodney W. Grimes /*
345b81b6b3SRodney W. Grimes  * Functions to provide access to special i386 instructions.
35f5d9a10bSMark Murray  * This in included in sys/systm.h, and that file should be
36f5d9a10bSMark Murray  * used in preference to this.
375b81b6b3SRodney W. Grimes  */
385b81b6b3SRodney W. Grimes 
396e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
40004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
416e393973SGarrett Wollman 
42a5f50ef9SJoerg Wunsch #ifndef _SYS_CDEFS_H_
43a5f50ef9SJoerg Wunsch #error this file needs sys/cdefs.h as a prerequisite
44a5f50ef9SJoerg Wunsch #endif
45a5f50ef9SJoerg Wunsch 
46eb1443c8SPeter Wemm struct region_descriptor;
47d74ac681SMatthew Dillon 
48e31fa854SDoug Rabson #define readb(va)	(*(volatile u_int8_t *) (va))
49e31fa854SDoug Rabson #define readw(va)	(*(volatile u_int16_t *) (va))
50e31fa854SDoug Rabson #define readl(va)	(*(volatile u_int32_t *) (va))
51afa88623SPeter Wemm #define readq(va)	(*(volatile u_int64_t *) (va))
52e31fa854SDoug Rabson 
53e31fa854SDoug Rabson #define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
54e31fa854SDoug Rabson #define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
55e31fa854SDoug Rabson #define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
56afa88623SPeter Wemm #define writeq(va, d)	(*(volatile u_int64_t *) (va) = (d))
57e31fa854SDoug Rabson 
58a5f50ef9SJoerg Wunsch #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
595b81b6b3SRodney W. Grimes 
605dbd168eSBruce Evans static __inline void
615dbd168eSBruce Evans breakpoint(void)
62004bedebSBruce Evans {
63004bedebSBruce Evans 	__asm __volatile("int $3");
645b81b6b3SRodney W. Grimes }
655b81b6b3SRodney W. Grimes 
66c83b1328SBruce Evans static __inline u_int
67c83b1328SBruce Evans bsfl(u_int mask)
68c83b1328SBruce Evans {
69c83b1328SBruce Evans 	u_int	result;
70c83b1328SBruce Evans 
713f9a462fSJohn Baldwin 	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
72c83b1328SBruce Evans 	return (result);
73c83b1328SBruce Evans }
74c83b1328SBruce Evans 
75176ce2b1SPeter Wemm static __inline u_long
76176ce2b1SPeter Wemm bsfq(u_long mask)
77176ce2b1SPeter Wemm {
78176ce2b1SPeter Wemm 	u_long	result;
79176ce2b1SPeter Wemm 
80176ce2b1SPeter Wemm 	__asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask));
81176ce2b1SPeter Wemm 	return (result);
82176ce2b1SPeter Wemm }
83176ce2b1SPeter Wemm 
84c83b1328SBruce Evans static __inline u_int
85c83b1328SBruce Evans bsrl(u_int mask)
86c83b1328SBruce Evans {
87c83b1328SBruce Evans 	u_int	result;
88c83b1328SBruce Evans 
893f9a462fSJohn Baldwin 	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
90c83b1328SBruce Evans 	return (result);
91c83b1328SBruce Evans }
92c83b1328SBruce Evans 
93176ce2b1SPeter Wemm static __inline u_long
94176ce2b1SPeter Wemm bsrq(u_long mask)
95176ce2b1SPeter Wemm {
96176ce2b1SPeter Wemm 	u_long	result;
97176ce2b1SPeter Wemm 
98176ce2b1SPeter Wemm 	__asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask));
99176ce2b1SPeter Wemm 	return (result);
100176ce2b1SPeter Wemm }
101176ce2b1SPeter Wemm 
102004bedebSBruce Evans static __inline void
1035b81b6b3SRodney W. Grimes disable_intr(void)
1045b81b6b3SRodney W. Grimes {
1058966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
1065b81b6b3SRodney W. Grimes }
1075b81b6b3SRodney W. Grimes 
108004bedebSBruce Evans static __inline void
109a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
110a983fdfeSDavid Malone {
111a983fdfeSDavid Malone 	__asm __volatile("cpuid"
112a983fdfeSDavid Malone 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
113a983fdfeSDavid Malone 			 :  "0" (ax));
114a983fdfeSDavid Malone }
115a983fdfeSDavid Malone 
116a983fdfeSDavid Malone static __inline void
117f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p)
118f6108b61SJacques Vidrine {
119f6108b61SJacques Vidrine 	__asm __volatile("cpuid"
120f6108b61SJacques Vidrine 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
121f6108b61SJacques Vidrine 			 :  "0" (ax), "c" (cx));
122f6108b61SJacques Vidrine }
123f6108b61SJacques Vidrine 
124f6108b61SJacques Vidrine static __inline void
1255b81b6b3SRodney W. Grimes enable_intr(void)
1265b81b6b3SRodney W. Grimes {
127fadc51bdSBruce Evans 	__asm __volatile("sti");
1285b81b6b3SRodney W. Grimes }
1295b81b6b3SRodney W. Grimes 
130a67ef0a7SBruce Evans #ifdef _KERNEL
131a67ef0a7SBruce Evans 
132264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
133bc35f5dcSPaul Saab #define        ffs(x)  __builtin_ffs(x)
134176ce2b1SPeter Wemm 
135176ce2b1SPeter Wemm #define	HAVE_INLINE_FFSL
136176ce2b1SPeter Wemm 
137176ce2b1SPeter Wemm static __inline int
138176ce2b1SPeter Wemm ffsl(long mask)
139176ce2b1SPeter Wemm {
140176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1);
141004bedebSBruce Evans }
142004bedebSBruce Evans 
14313f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
14413f588f8SGarrett Wollman 
14513f588f8SGarrett Wollman static __inline int
14613f588f8SGarrett Wollman fls(int mask)
14713f588f8SGarrett Wollman {
1487e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
14913f588f8SGarrett Wollman }
15013f588f8SGarrett Wollman 
151176ce2b1SPeter Wemm #define	HAVE_INLINE_FLSL
152176ce2b1SPeter Wemm 
153176ce2b1SPeter Wemm static __inline int
154176ce2b1SPeter Wemm flsl(long mask)
155176ce2b1SPeter Wemm {
156176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
157176ce2b1SPeter Wemm }
158176ce2b1SPeter Wemm 
159a67ef0a7SBruce Evans #endif /* _KERNEL */
160a67ef0a7SBruce Evans 
161d7ee4425SMark Murray static __inline void
162d7ee4425SMark Murray halt(void)
163d7ee4425SMark Murray {
164d7ee4425SMark Murray 	__asm __volatile("hlt");
165d7ee4425SMark Murray }
166d7ee4425SMark Murray 
167a5f50ef9SJoerg Wunsch #if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3
168004bedebSBruce Evans 
169004bedebSBruce Evans #define	inb(port)		inbv(port)
170004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
171004bedebSBruce Evans 
172a5f50ef9SJoerg Wunsch #else /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3 */
173004bedebSBruce Evans 
174004bedebSBruce Evans /*
1758089a043SBruce Evans  * The following complications are to get around gcc not having a
1768089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1778089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1788089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1798089a043SBruce Evans  * the non-working version gets optimized away.
1808089a043SBruce Evans  *
181004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
182004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
183004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
184388dfa71SBruce Evans  *
185388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
186388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
187388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
188388dfa71SBruce Evans  * careful to avoid generating warnings.
189004bedebSBruce Evans  */
190388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
191004bedebSBruce Evans 	u_char	_data;							\
192388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
193388dfa71SBruce Evans 	    && (port) < 0x10000)					\
194004bedebSBruce Evans 		_data = inbc(port);					\
195004bedebSBruce Evans 	else								\
196004bedebSBruce Evans 		_data = inbv(port);					\
197004bedebSBruce Evans 	_data; })
198004bedebSBruce Evans 
199388dfa71SBruce Evans #define	outb(port, data) (						\
200388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
201388dfa71SBruce Evans 	&& (port) < 0x10000						\
202004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
203004bedebSBruce Evans 
204004bedebSBruce Evans static __inline u_char
205004bedebSBruce Evans inbc(u_int port)
206004bedebSBruce Evans {
207004bedebSBruce Evans 	u_char	data;
208004bedebSBruce Evans 
2098089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
210004bedebSBruce Evans 	return (data);
211004bedebSBruce Evans }
212004bedebSBruce Evans 
213004bedebSBruce Evans static __inline void
214004bedebSBruce Evans outbc(u_int port, u_char data)
215004bedebSBruce Evans {
2168089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
217004bedebSBruce Evans }
218004bedebSBruce Evans 
219cf4e1c46SPeter Wemm #endif /* __GNUCLIKE_BUILTIN_CONSTANT_P  && __GNUCLIKE_ASM >= 3*/
220004bedebSBruce Evans 
221004bedebSBruce Evans static __inline u_char
222004bedebSBruce Evans inbv(u_int port)
223004bedebSBruce Evans {
224004bedebSBruce Evans 	u_char	data;
225004bedebSBruce Evans 	/*
226004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
227004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
228004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
229004bedebSBruce Evans 	 */
230004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
231004bedebSBruce Evans 	return (data);
232004bedebSBruce Evans }
233004bedebSBruce Evans 
23400be8601SBruce Evans static __inline u_int
235004bedebSBruce Evans inl(u_int port)
236004bedebSBruce Evans {
23700be8601SBruce Evans 	u_int	data;
238004bedebSBruce Evans 
239004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
240004bedebSBruce Evans 	return (data);
241004bedebSBruce Evans }
242004bedebSBruce Evans 
243004bedebSBruce Evans static __inline void
244004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
245004bedebSBruce Evans {
246004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
2473f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2483f9a462fSJohn Baldwin 			 : "d" (port)
249896763faSBruce Evans 			 : "memory");
250004bedebSBruce Evans }
251004bedebSBruce Evans 
252004bedebSBruce Evans static __inline void
253004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
254004bedebSBruce Evans {
255004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
2563f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2573f9a462fSJohn Baldwin 			 : "d" (port)
258896763faSBruce Evans 			 : "memory");
259004bedebSBruce Evans }
260004bedebSBruce Evans 
261004bedebSBruce Evans static __inline void
262004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
263004bedebSBruce Evans {
264004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
2653f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2663f9a462fSJohn Baldwin 			 : "d" (port)
267896763faSBruce Evans 			 : "memory");
268004bedebSBruce Evans }
269004bedebSBruce Evans 
270ece15d78SBruce Evans static __inline void
2714c024bbdSKATO Takenori invd(void)
2724c024bbdSKATO Takenori {
2734c024bbdSKATO Takenori 	__asm __volatile("invd");
2744c024bbdSKATO Takenori }
2754c024bbdSKATO Takenori 
276004bedebSBruce Evans static __inline u_short
277004bedebSBruce Evans inw(u_int port)
278004bedebSBruce Evans {
279004bedebSBruce Evans 	u_short	data;
280004bedebSBruce Evans 
281004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
282004bedebSBruce Evans 	return (data);
283004bedebSBruce Evans }
284004bedebSBruce Evans 
285004bedebSBruce Evans static __inline void
286004bedebSBruce Evans outbv(u_int port, u_char data)
287004bedebSBruce Evans {
288004bedebSBruce Evans 	u_char	al;
289004bedebSBruce Evans 	/*
290004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
291004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
292004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
293004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
294004bedebSBruce Evans 	 */
295004bedebSBruce Evans 	al = data;
296004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
297004bedebSBruce Evans }
298004bedebSBruce Evans 
299004bedebSBruce Evans static __inline void
30000be8601SBruce Evans outl(u_int port, u_int data)
301004bedebSBruce Evans {
302004bedebSBruce Evans 	/*
303004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
304004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
305004bedebSBruce Evans 	 * assignment for them.
306004bedebSBruce Evans 	 */
307004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
308004bedebSBruce Evans }
309004bedebSBruce Evans 
310004bedebSBruce Evans static __inline void
311e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
312004bedebSBruce Evans {
313004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
3143f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3153f9a462fSJohn Baldwin 			 : "d" (port));
316004bedebSBruce Evans }
317004bedebSBruce Evans 
318004bedebSBruce Evans static __inline void
319e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
320004bedebSBruce Evans {
321004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
3223f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3233f9a462fSJohn Baldwin 			 : "d" (port));
324004bedebSBruce Evans }
325004bedebSBruce Evans 
326004bedebSBruce Evans static __inline void
327e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
328004bedebSBruce Evans {
329004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
3303f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3313f9a462fSJohn Baldwin 			 : "d" (port));
332004bedebSBruce Evans }
333004bedebSBruce Evans 
334004bedebSBruce Evans static __inline void
335004bedebSBruce Evans outw(u_int port, u_short data)
336004bedebSBruce Evans {
337004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
338004bedebSBruce Evans }
339004bedebSBruce Evans 
3402be69f32SJohn Baldwin static __inline void
3416b8c6989SJohn Baldwin ia32_pause(void)
3422be69f32SJohn Baldwin {
3432be69f32SJohn Baldwin 	__asm __volatile("pause");
3442be69f32SJohn Baldwin }
3452be69f32SJohn Baldwin 
346afa88623SPeter Wemm static __inline u_long
347afa88623SPeter Wemm read_rflags(void)
3485b81b6b3SRodney W. Grimes {
349afa88623SPeter Wemm 	u_long	rf;
350004bedebSBruce Evans 
351afa88623SPeter Wemm 	__asm __volatile("pushfq; popq %0" : "=r" (rf));
352afa88623SPeter Wemm 	return (rf);
3535b81b6b3SRodney W. Grimes }
3545b81b6b3SRodney W. Grimes 
35500be8601SBruce Evans static __inline u_int64_t
3565dbd168eSBruce Evans rdmsr(u_int msr)
3575dbd168eSBruce Evans {
358afa88623SPeter Wemm 	u_int32_t low, high;
3595dbd168eSBruce Evans 
360afa88623SPeter Wemm 	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
361afa88623SPeter Wemm 	return (low | ((u_int64_t)high << 32));
3625dbd168eSBruce Evans }
3635dbd168eSBruce Evans 
36400be8601SBruce Evans static __inline u_int64_t
3655dbd168eSBruce Evans rdpmc(u_int pmc)
3665dbd168eSBruce Evans {
367afa88623SPeter Wemm 	u_int32_t low, high;
3685dbd168eSBruce Evans 
369afa88623SPeter Wemm 	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
370afa88623SPeter Wemm 	return (low | ((u_int64_t)high << 32));
3715dbd168eSBruce Evans }
3725dbd168eSBruce Evans 
37300be8601SBruce Evans static __inline u_int64_t
3745dbd168eSBruce Evans rdtsc(void)
3755dbd168eSBruce Evans {
376afa88623SPeter Wemm 	u_int32_t low, high;
3775dbd168eSBruce Evans 
378afa88623SPeter Wemm 	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
379afa88623SPeter Wemm 	return (low | ((u_int64_t)high << 32));
3805dbd168eSBruce Evans }
3815dbd168eSBruce Evans 
382004bedebSBruce Evans static __inline void
3834c024bbdSKATO Takenori wbinvd(void)
3844c024bbdSKATO Takenori {
3854c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3864c024bbdSKATO Takenori }
3874c024bbdSKATO Takenori 
3884c024bbdSKATO Takenori static __inline void
389afa88623SPeter Wemm write_rflags(u_long rf)
3905b81b6b3SRodney W. Grimes {
391afa88623SPeter Wemm 	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
3925b81b6b3SRodney W. Grimes }
3935b81b6b3SRodney W. Grimes 
394d69e8502SGarrett Wollman static __inline void
39500be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
396d69e8502SGarrett Wollman {
397afa88623SPeter Wemm 	u_int32_t low, high;
398afa88623SPeter Wemm 
399afa88623SPeter Wemm 	low = newval;
400afa88623SPeter Wemm 	high = newval >> 32;
401afa88623SPeter Wemm 	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
402d69e8502SGarrett Wollman }
403d69e8502SGarrett Wollman 
404f1b665c8SPeter Wemm static __inline void
405afa88623SPeter Wemm load_cr0(u_long data)
406f1b665c8SPeter Wemm {
407f1b665c8SPeter Wemm 
408afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr0" : : "r" (data));
409f1b665c8SPeter Wemm }
410f1b665c8SPeter Wemm 
411afa88623SPeter Wemm static __inline u_long
412f1b665c8SPeter Wemm rcr0(void)
413f1b665c8SPeter Wemm {
414afa88623SPeter Wemm 	u_long	data;
415f1b665c8SPeter Wemm 
416afa88623SPeter Wemm 	__asm __volatile("movq %%cr0,%0" : "=r" (data));
417f1b665c8SPeter Wemm 	return (data);
418f1b665c8SPeter Wemm }
419f1b665c8SPeter Wemm 
420afa88623SPeter Wemm static __inline u_long
421f1b665c8SPeter Wemm rcr2(void)
422f1b665c8SPeter Wemm {
423afa88623SPeter Wemm 	u_long	data;
424f1b665c8SPeter Wemm 
425afa88623SPeter Wemm 	__asm __volatile("movq %%cr2,%0" : "=r" (data));
426f1b665c8SPeter Wemm 	return (data);
427f1b665c8SPeter Wemm }
428f1b665c8SPeter Wemm 
429f1b665c8SPeter Wemm static __inline void
430afa88623SPeter Wemm load_cr3(u_long data)
431f1b665c8SPeter Wemm {
432f1b665c8SPeter Wemm 
433afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
434f1b665c8SPeter Wemm }
435f1b665c8SPeter Wemm 
436afa88623SPeter Wemm static __inline u_long
437f1b665c8SPeter Wemm rcr3(void)
438f1b665c8SPeter Wemm {
439afa88623SPeter Wemm 	u_long	data;
440f1b665c8SPeter Wemm 
441afa88623SPeter Wemm 	__asm __volatile("movq %%cr3,%0" : "=r" (data));
442f1b665c8SPeter Wemm 	return (data);
443f1b665c8SPeter Wemm }
444f1b665c8SPeter Wemm 
445f1b665c8SPeter Wemm static __inline void
446afa88623SPeter Wemm load_cr4(u_long data)
447f1b665c8SPeter Wemm {
448afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr4" : : "r" (data));
449f1b665c8SPeter Wemm }
450f1b665c8SPeter Wemm 
451afa88623SPeter Wemm static __inline u_long
452f1b665c8SPeter Wemm rcr4(void)
453f1b665c8SPeter Wemm {
454afa88623SPeter Wemm 	u_long	data;
455f1b665c8SPeter Wemm 
456afa88623SPeter Wemm 	__asm __volatile("movq %%cr4,%0" : "=r" (data));
457f1b665c8SPeter Wemm 	return (data);
458f1b665c8SPeter Wemm }
459f1b665c8SPeter Wemm 
460f1b665c8SPeter Wemm /*
461f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
462f1b665c8SPeter Wemm  */
463f1b665c8SPeter Wemm static __inline void
464f1b665c8SPeter Wemm invltlb(void)
465f1b665c8SPeter Wemm {
466f1b665c8SPeter Wemm 
467f1b665c8SPeter Wemm 	load_cr3(rcr3());
468f1b665c8SPeter Wemm }
469f1b665c8SPeter Wemm 
470f1b665c8SPeter Wemm /*
471f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
472f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
473f1b665c8SPeter Wemm  */
474f1b665c8SPeter Wemm static __inline void
475afa88623SPeter Wemm invlpg(u_long addr)
476f1b665c8SPeter Wemm {
477f1b665c8SPeter Wemm 
478f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
479f1b665c8SPeter Wemm }
480f1b665c8SPeter Wemm 
4815206bca1SLuoqi Chen static __inline u_int
4825206bca1SLuoqi Chen rfs(void)
4835206bca1SLuoqi Chen {
484d1fc2022SDavid Xu 	u_int sel;
485d1fc2022SDavid Xu 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4865206bca1SLuoqi Chen 	return (sel);
4875206bca1SLuoqi Chen }
4885206bca1SLuoqi Chen 
4895206bca1SLuoqi Chen static __inline u_int
4905206bca1SLuoqi Chen rgs(void)
4915206bca1SLuoqi Chen {
492d1fc2022SDavid Xu 	u_int sel;
493d1fc2022SDavid Xu 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4945206bca1SLuoqi Chen 	return (sel);
4955206bca1SLuoqi Chen }
4965206bca1SLuoqi Chen 
497cd0149e3SPeter Wemm static __inline u_int
498cd0149e3SPeter Wemm rss(void)
499cd0149e3SPeter Wemm {
500cd0149e3SPeter Wemm 	u_int sel;
501cd0149e3SPeter Wemm 	__asm __volatile("movl %%ss,%0" : "=rm" (sel));
502cd0149e3SPeter Wemm 	return (sel);
503cd0149e3SPeter Wemm }
504cd0149e3SPeter Wemm 
5055206bca1SLuoqi Chen static __inline void
506d85631c4SPeter Wemm load_ds(u_int sel)
507d85631c4SPeter Wemm {
508d85631c4SPeter Wemm 	__asm __volatile("movl %0,%%ds" : : "rm" (sel));
509d85631c4SPeter Wemm }
510d85631c4SPeter Wemm 
511d85631c4SPeter Wemm static __inline void
512d85631c4SPeter Wemm load_es(u_int sel)
513d85631c4SPeter Wemm {
514d85631c4SPeter Wemm 	__asm __volatile("movl %0,%%es" : : "rm" (sel));
515d85631c4SPeter Wemm }
516d85631c4SPeter Wemm 
51766247efaSJeff Roberson static inline void
51866247efaSJeff Roberson cpu_monitor(const void *addr, int extensions, int hints)
51966247efaSJeff Roberson {
52066247efaSJeff Roberson 	__asm __volatile("monitor;"
52166247efaSJeff Roberson 	    : :"a" (addr), "c" (extensions), "d"(hints));
52266247efaSJeff Roberson }
52366247efaSJeff Roberson 
52466247efaSJeff Roberson static inline void
52566247efaSJeff Roberson cpu_mwait(int extensions, int hints)
52666247efaSJeff Roberson {
52766247efaSJeff Roberson 	__asm __volatile("mwait;" : :"a" (hints), "c" (extensions));
52866247efaSJeff Roberson }
52966247efaSJeff Roberson 
530c0a54ff6SPeter Wemm #ifdef _KERNEL
531c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */
532c0a54ff6SPeter Wemm #ifndef	MSR_FSBASE
533c0a54ff6SPeter Wemm #define	MSR_FSBASE	0xc0000100
534c0a54ff6SPeter Wemm #endif
535c0a54ff6SPeter Wemm static __inline void
536c0a54ff6SPeter Wemm load_fs(u_int sel)
537c0a54ff6SPeter Wemm {
538c0a54ff6SPeter Wemm 	register u_int32_t fsbase __asm("ecx");
539c0a54ff6SPeter Wemm 
540c0a54ff6SPeter Wemm 	/* Preserve the fsbase value across the selector load */
541c0a54ff6SPeter Wemm 	fsbase = MSR_FSBASE;
542c0a54ff6SPeter Wemm         __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
543c0a54ff6SPeter Wemm             : : "rm" (sel), "c" (fsbase) : "eax", "edx");
544c0a54ff6SPeter Wemm }
545c0a54ff6SPeter Wemm 
546c0a54ff6SPeter Wemm #ifndef	MSR_GSBASE
547c0a54ff6SPeter Wemm #define	MSR_GSBASE	0xc0000101
548c0a54ff6SPeter Wemm #endif
549c0a54ff6SPeter Wemm static __inline void
550c0a54ff6SPeter Wemm load_gs(u_int sel)
551c0a54ff6SPeter Wemm {
552c0a54ff6SPeter Wemm 	register u_int32_t gsbase __asm("ecx");
553c0a54ff6SPeter Wemm 
554c0a54ff6SPeter Wemm 	/*
555c0a54ff6SPeter Wemm 	 * Preserve the gsbase value across the selector load.
556c0a54ff6SPeter Wemm 	 * Note that we have to disable interrupts because the gsbase
557c0a54ff6SPeter Wemm 	 * being trashed happens to be the kernel gsbase at the time.
558c0a54ff6SPeter Wemm 	 */
559c0a54ff6SPeter Wemm 	gsbase = MSR_GSBASE;
560c0a54ff6SPeter Wemm         __asm __volatile("pushfq; cli; rdmsr; movl %0,%%gs; wrmsr; popfq"
561c0a54ff6SPeter Wemm             : : "rm" (sel), "c" (gsbase) : "eax", "edx");
562c0a54ff6SPeter Wemm }
563c0a54ff6SPeter Wemm #else
564c0a54ff6SPeter Wemm /* Usable by userland */
565d85631c4SPeter Wemm static __inline void
5665206bca1SLuoqi Chen load_fs(u_int sel)
5675206bca1SLuoqi Chen {
568e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
5695206bca1SLuoqi Chen }
5705206bca1SLuoqi Chen 
5715206bca1SLuoqi Chen static __inline void
5725206bca1SLuoqi Chen load_gs(u_int sel)
5735206bca1SLuoqi Chen {
574e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
5755206bca1SLuoqi Chen }
576c0a54ff6SPeter Wemm #endif
5775206bca1SLuoqi Chen 
578eb1443c8SPeter Wemm static __inline void
579eb1443c8SPeter Wemm lidt(struct region_descriptor *addr)
580eb1443c8SPeter Wemm {
581eb1443c8SPeter Wemm 	__asm __volatile("lidt (%0)" : : "r" (addr));
582eb1443c8SPeter Wemm }
583eb1443c8SPeter Wemm 
584eb1443c8SPeter Wemm static __inline void
585eb1443c8SPeter Wemm lldt(u_short sel)
586eb1443c8SPeter Wemm {
587eb1443c8SPeter Wemm 	__asm __volatile("lldt %0" : : "r" (sel));
588eb1443c8SPeter Wemm }
589eb1443c8SPeter Wemm 
590eb1443c8SPeter Wemm static __inline void
591eb1443c8SPeter Wemm ltr(u_short sel)
592eb1443c8SPeter Wemm {
593eb1443c8SPeter Wemm 	__asm __volatile("ltr %0" : : "r" (sel));
594eb1443c8SPeter Wemm }
595eb1443c8SPeter Wemm 
5961182b177SPeter Wemm static __inline u_int64_t
5971182b177SPeter Wemm rdr0(void)
5981182b177SPeter Wemm {
5991182b177SPeter Wemm 	u_int64_t data;
6001182b177SPeter Wemm 	__asm __volatile("movq %%dr0,%0" : "=r" (data));
6011182b177SPeter Wemm 	return (data);
6021182b177SPeter Wemm }
6031182b177SPeter Wemm 
6041182b177SPeter Wemm static __inline void
6051182b177SPeter Wemm load_dr0(u_int64_t dr0)
6061182b177SPeter Wemm {
6071182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
6081182b177SPeter Wemm }
6091182b177SPeter Wemm 
6101182b177SPeter Wemm static __inline u_int64_t
6111182b177SPeter Wemm rdr1(void)
6121182b177SPeter Wemm {
6131182b177SPeter Wemm 	u_int64_t data;
6141182b177SPeter Wemm 	__asm __volatile("movq %%dr1,%0" : "=r" (data));
6151182b177SPeter Wemm 	return (data);
6161182b177SPeter Wemm }
6171182b177SPeter Wemm 
6181182b177SPeter Wemm static __inline void
6191182b177SPeter Wemm load_dr1(u_int64_t dr1)
6201182b177SPeter Wemm {
6211182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
6221182b177SPeter Wemm }
6231182b177SPeter Wemm 
6241182b177SPeter Wemm static __inline u_int64_t
6251182b177SPeter Wemm rdr2(void)
6261182b177SPeter Wemm {
6271182b177SPeter Wemm 	u_int64_t data;
6281182b177SPeter Wemm 	__asm __volatile("movq %%dr2,%0" : "=r" (data));
6291182b177SPeter Wemm 	return (data);
6301182b177SPeter Wemm }
6311182b177SPeter Wemm 
6321182b177SPeter Wemm static __inline void
6331182b177SPeter Wemm load_dr2(u_int64_t dr2)
6341182b177SPeter Wemm {
6351182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
6361182b177SPeter Wemm }
6371182b177SPeter Wemm 
6381182b177SPeter Wemm static __inline u_int64_t
6391182b177SPeter Wemm rdr3(void)
6401182b177SPeter Wemm {
6411182b177SPeter Wemm 	u_int64_t data;
6421182b177SPeter Wemm 	__asm __volatile("movq %%dr3,%0" : "=r" (data));
6431182b177SPeter Wemm 	return (data);
6441182b177SPeter Wemm }
6451182b177SPeter Wemm 
6461182b177SPeter Wemm static __inline void
6471182b177SPeter Wemm load_dr3(u_int64_t dr3)
6481182b177SPeter Wemm {
6491182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
6501182b177SPeter Wemm }
6511182b177SPeter Wemm 
6521182b177SPeter Wemm static __inline u_int64_t
6531182b177SPeter Wemm rdr4(void)
6541182b177SPeter Wemm {
6551182b177SPeter Wemm 	u_int64_t data;
6561182b177SPeter Wemm 	__asm __volatile("movq %%dr4,%0" : "=r" (data));
6571182b177SPeter Wemm 	return (data);
6581182b177SPeter Wemm }
6591182b177SPeter Wemm 
6601182b177SPeter Wemm static __inline void
6611182b177SPeter Wemm load_dr4(u_int64_t dr4)
6621182b177SPeter Wemm {
6631182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr4" : : "r" (dr4));
6641182b177SPeter Wemm }
6651182b177SPeter Wemm 
6661182b177SPeter Wemm static __inline u_int64_t
6671182b177SPeter Wemm rdr5(void)
6681182b177SPeter Wemm {
6691182b177SPeter Wemm 	u_int64_t data;
6701182b177SPeter Wemm 	__asm __volatile("movq %%dr5,%0" : "=r" (data));
6711182b177SPeter Wemm 	return (data);
6721182b177SPeter Wemm }
6731182b177SPeter Wemm 
6741182b177SPeter Wemm static __inline void
6751182b177SPeter Wemm load_dr5(u_int64_t dr5)
6761182b177SPeter Wemm {
6771182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr5" : : "r" (dr5));
6781182b177SPeter Wemm }
6791182b177SPeter Wemm 
6801182b177SPeter Wemm static __inline u_int64_t
6811182b177SPeter Wemm rdr6(void)
6821182b177SPeter Wemm {
6831182b177SPeter Wemm 	u_int64_t data;
6841182b177SPeter Wemm 	__asm __volatile("movq %%dr6,%0" : "=r" (data));
6851182b177SPeter Wemm 	return (data);
6861182b177SPeter Wemm }
6871182b177SPeter Wemm 
6881182b177SPeter Wemm static __inline void
6891182b177SPeter Wemm load_dr6(u_int64_t dr6)
6901182b177SPeter Wemm {
6911182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
6921182b177SPeter Wemm }
6931182b177SPeter Wemm 
6941182b177SPeter Wemm static __inline u_int64_t
6951182b177SPeter Wemm rdr7(void)
6961182b177SPeter Wemm {
6971182b177SPeter Wemm 	u_int64_t data;
6981182b177SPeter Wemm 	__asm __volatile("movq %%dr7,%0" : "=r" (data));
6991182b177SPeter Wemm 	return (data);
7001182b177SPeter Wemm }
7011182b177SPeter Wemm 
7021182b177SPeter Wemm static __inline void
7031182b177SPeter Wemm load_dr7(u_int64_t dr7)
7041182b177SPeter Wemm {
7051182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
7061182b177SPeter Wemm }
7071182b177SPeter Wemm 
708ba74981eSWarner Losh static __inline register_t
709ba74981eSWarner Losh intr_disable(void)
710ba74981eSWarner Losh {
711afa88623SPeter Wemm 	register_t rflags;
712ba74981eSWarner Losh 
713afa88623SPeter Wemm 	rflags = read_rflags();
714ba74981eSWarner Losh 	disable_intr();
715afa88623SPeter Wemm 	return (rflags);
716ba74981eSWarner Losh }
717ba74981eSWarner Losh 
718ba74981eSWarner Losh static __inline void
719afa88623SPeter Wemm intr_restore(register_t rflags)
720ba74981eSWarner Losh {
721afa88623SPeter Wemm 	write_rflags(rflags);
722ba74981eSWarner Losh }
723ba74981eSWarner Losh 
724a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
7255b81b6b3SRodney W. Grimes 
726b63dc6adSAlfred Perlstein int	breakpoint(void);
727b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
728b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
729b63dc6adSAlfred Perlstein void	disable_intr(void);
730b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
731b63dc6adSAlfred Perlstein void	enable_intr(void);
732d7ee4425SMark Murray void	halt(void);
7334f6c19e5SPeter Wemm void	ia32_pause(void);
734b63dc6adSAlfred Perlstein u_char	inb(u_int port);
735b63dc6adSAlfred Perlstein u_int	inl(u_int port);
736b63dc6adSAlfred Perlstein void	insb(u_int port, void *addr, size_t cnt);
737b63dc6adSAlfred Perlstein void	insl(u_int port, void *addr, size_t cnt);
738b63dc6adSAlfred Perlstein void	insw(u_int port, void *addr, size_t cnt);
7394f6c19e5SPeter Wemm register_t	intr_disable(void);
7404f6c19e5SPeter Wemm void	intr_restore(register_t rf);
741b63dc6adSAlfred Perlstein void	invd(void);
742b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
743b63dc6adSAlfred Perlstein void	invltlb(void);
744b63dc6adSAlfred Perlstein u_short	inw(u_int port);
745eb1443c8SPeter Wemm void	lidt(struct region_descriptor *addr);
746eb1443c8SPeter Wemm void	lldt(u_short sel);
7474f6c19e5SPeter Wemm void	load_cr0(u_long cr0);
7484f6c19e5SPeter Wemm void	load_cr3(u_long cr3);
7494f6c19e5SPeter Wemm void	load_cr4(u_long cr4);
7504f6c19e5SPeter Wemm void	load_dr0(u_int64_t dr0);
7514f6c19e5SPeter Wemm void	load_dr1(u_int64_t dr1);
7524f6c19e5SPeter Wemm void	load_dr2(u_int64_t dr2);
7534f6c19e5SPeter Wemm void	load_dr3(u_int64_t dr3);
7544f6c19e5SPeter Wemm void	load_dr4(u_int64_t dr4);
7554f6c19e5SPeter Wemm void	load_dr5(u_int64_t dr5);
7564f6c19e5SPeter Wemm void	load_dr6(u_int64_t dr6);
7574f6c19e5SPeter Wemm void	load_dr7(u_int64_t dr7);
7584f6c19e5SPeter Wemm void	load_fs(u_int sel);
7594f6c19e5SPeter Wemm void	load_gs(u_int sel);
760eb1443c8SPeter Wemm void	ltr(u_short sel);
761b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
762b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
7631bcf24eeSLukas Ertl void	outsb(u_int port, const void *addr, size_t cnt);
7641bcf24eeSLukas Ertl void	outsl(u_int port, const void *addr, size_t cnt);
7651bcf24eeSLukas Ertl void	outsw(u_int port, const void *addr, size_t cnt);
766b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
7674f6c19e5SPeter Wemm u_long	rcr0(void);
7684f6c19e5SPeter Wemm u_long	rcr2(void);
7694f6c19e5SPeter Wemm u_long	rcr3(void);
7704f6c19e5SPeter Wemm u_long	rcr4(void);
771b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr);
772b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc);
7734f6c19e5SPeter Wemm u_int64_t rdr0(void);
7744f6c19e5SPeter Wemm u_int64_t rdr1(void);
7754f6c19e5SPeter Wemm u_int64_t rdr2(void);
7764f6c19e5SPeter Wemm u_int64_t rdr3(void);
7774f6c19e5SPeter Wemm u_int64_t rdr4(void);
7784f6c19e5SPeter Wemm u_int64_t rdr5(void);
7794f6c19e5SPeter Wemm u_int64_t rdr6(void);
7804f6c19e5SPeter Wemm u_int64_t rdr7(void);
781b63dc6adSAlfred Perlstein u_int64_t rdtsc(void);
782afa88623SPeter Wemm u_int	read_rflags(void);
7834f6c19e5SPeter Wemm u_int	rfs(void);
7844f6c19e5SPeter Wemm u_int	rgs(void);
785b63dc6adSAlfred Perlstein void	wbinvd(void);
786afa88623SPeter Wemm void	write_rflags(u_int rf);
787b63dc6adSAlfred Perlstein void	wrmsr(u_int msr, u_int64_t newval);
788004bedebSBruce Evans 
789a5f50ef9SJoerg Wunsch #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
7905b81b6b3SRodney W. Grimes 
791b63dc6adSAlfred Perlstein void	reset_dbregs(void);
792d74ac681SMatthew Dillon 
793e085f869SStanislav Sedov #ifdef _KERNEL
794e085f869SStanislav Sedov int	rdmsr_safe(u_int msr, uint64_t *val);
795e085f869SStanislav Sedov int	wrmsr_safe(u_int msr, uint64_t newval);
796e085f869SStanislav Sedov #endif
797e085f869SStanislav Sedov 
798004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
799