code:
/*-
 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/apicvar.h 212541 2010-09-13 07:25:35Z mav $
 */

#ifndef _MACHINE_APICVAR_H_
#define _MACHINE_APICVAR_H_

#include <machine/segments.h>

/*
 * Local && I/O APIC variable definitions.
 */

/*
 * Layout of local APIC interrupt vectors:
 *
 *	0xff (255)  +-------------+
 *                  |             | 15 (Spurious / IPIs / Local Interrupts)
 *	0xf0 (240)  +-------------+
 *                  |             | 14 (I/O Interrupts / Timer)
 *	0xe0 (224)  +-------------+
 *                  |             | 13 (I/O Interrupts)
 *	0xd0 (208)  +-------------+
 *                  |             | 12 (I/O Interrupts)
 *	0xc0 (192)  +-------------+
 *                  |             | 11 (I/O Interrupts)
 *	0xb0 (176)  +-------------+
 *                  |             | 10 (I/O Interrupts)
 *	0xa0 (160)  +-------------+
 *                  |             | 9 (I/O Interrupts)
 *	0x90 (144)  +-------------+
 *                  |             | 8 (I/O Interrupts / System Calls)
 *	0x80 (128)  +-------------+
 *                  |             | 7 (I/O Interrupts)
 *	0x70 (112)  +-------------+
 *                  |             | 6 (I/O Interrupts)
 *	0x60 (96)   +-------------+
 *                  |             | 5 (I/O Interrupts)
 *	0x50 (80)   +-------------+
 *                  |             | 4 (I/O Interrupts)
 *	0x40 (64)   +-------------+
 *                  |             | 3 (I/O Interrupts)
 *	0x30 (48)   +-------------+
 *                  |             | 2 (ATPIC Interrupts)
 *	0x20 (32)   +-------------+
 *                  |             | 1 (Exceptions, traps, faults, etc.)
 *	0x10 (16)   +-------------+
 *                  |             | 0 (Exceptions, traps, faults, etc.)
 *	0x00 (0)    +-------------+
 *
 * Note: 0x80 needs to be handled specially and not allocated to an
 * I/O device!
 */

#define	MAX_APIC_ID	0xfe
#define	APIC_ID_ALL	0xff

/* I/O Interrupts are used for external devices such as ISA, PCI, etc. */
#define	APIC_IO_INTS	(IDT_IO_INTS + 16)
#define	APIC_NUM_IOINTS	191

/* The timer interrupt is used for clock handling and drives hardclock, etc. */
#define	APIC_TIMER_INT	(APIC_IO_INTS + APIC_NUM_IOINTS)

/*
 ********************* !!! WARNING !!! ******************************
 * Each local apic has an interrupt receive fifo that is two entries deep
 * for each interrupt priority class (higher 4 bits of interrupt vector).
 * Once the fifo is full the APIC can no longer receive interrupts for this
 * class and sending IPIs from other CPUs will be blocked.
 * To avoid deadlocks there should be no more than two IPI interrupts
 * pending at the same time.
 * Currently this is guaranteed by dividing the IPIs in two groups that have
 * each at most one IPI interrupt pending. The first group is protected by the
 * smp_ipi_mtx and waits for the completion of the IPI (Only one IPI user
 * at a time) The second group uses a single interrupt and a bitmap to avoid
 * redundant IPI interrupts.
 */

/* Interrupts for local APIC LVT entries other than the timer. */
#define	APIC_LOCAL_INTS	240
#define	APIC_ERROR_INT	APIC_LOCAL_INTS
#define	APIC_THERMAL_INT (APIC_LOCAL_INTS + 1)
#define	APIC_CMC_INT	(APIC_LOCAL_INTS + 2)

#define	APIC_IPI_INTS	(APIC_LOCAL_INTS + 3)
#define	IPI_RENDEZVOUS	(APIC_IPI_INTS)		/* Inter-CPU rendezvous. */
#define	IPI_INVLTLB	(APIC_IPI_INTS + 1)	/* TLB Shootdown IPIs */
#define	IPI_INVLPG	(APIC_IPI_INTS + 2)
#define	IPI_INVLRNG	(APIC_IPI_INTS + 3)
#define	IPI_INVLCACHE	(APIC_IPI_INTS + 4)
/* Vector to handle bitmap based IPIs */
#define	IPI_BITMAP_VECTOR	(APIC_IPI_INTS + 6)

/* IPIs handled by IPI_BITMAPED_VECTOR  (XXX ups is there a better place?) */
#define	IPI_AST		0 	/* Generate software trap. */
#define IPI_PREEMPT     1
#define IPI_HARDCLOCK   2
#define IPI_BITMAP_LAST IPI_HARDCLOCK
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)

#define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
#define	IPI_SUSPEND	(APIC_IPI_INTS + 8)	/* Suspend CPU until restarted. */
#define	IPI_STOP_HARD	(APIC_IPI_INTS + 9)	/* Stop CPU with a NMI. */

/*
 * The spurious interrupt can share the priority class with the IPIs since
 * it is not a normal interrupt. (Does not use the APIC's interrupt fifo)
 */
#define	APIC_SPURIOUS_INT 255

#define	LVT_LINT0	0
#define	LVT_LINT1	1
#define	LVT_TIMER	2
#define	LVT_ERROR	3
#define	LVT_PMC		4
#define	LVT_THERMAL	5
#define	LVT_CMCI	6
#define	LVT_MAX		LVT_CMCI

#ifndef LOCORE

#define	APIC_IPI_DEST_SELF	-1
#define	APIC_IPI_DEST_ALL	-2
#define	APIC_IPI_DEST_OTHERS	-3

#define	APIC_BUS_UNKNOWN	-1
#define	APIC_BUS_ISA		0
#define	APIC_BUS_EISA		1
#define	APIC_BUS_PCI		2
#define	APIC_BUS_MAX		APIC_BUS_PCI

/*
 * An APIC enumerator is a psuedo bus driver that enumerates APIC's including
 * CPU's and I/O APIC's.
 */
struct apic_enumerator {
	const char *apic_name;
	int (*apic_probe)(void);
	int (*apic_probe_cpus)(void);
	int (*apic_setup_local)(void);
	int (*apic_setup_io)(void);
	SLIST_ENTRY(apic_enumerator) apic_next;
};

inthand_t
	IDTVEC(apic_isr1), IDTVEC(apic_isr2), IDTVEC(apic_isr3),
	IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6),
	IDTVEC(apic_isr7), IDTVEC(cmcint), IDTVEC(errorint),
	IDTVEC(spuriousint), IDTVEC(timerint);

extern vm_paddr_t lapic_paddr;
extern int apic_cpuids[];

u_int	apic_alloc_vector(u_int apic_id, u_int irq);
u_int	apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count,
	    u_int align);
void	apic_disable_vector(u_int apic_id, u_int vector);
void	apic_enable_vector(u_int apic_id, u_int vector);
void	apic_free_vector(u_int apic_id, u_int vector, u_int irq);
u_int	apic_idt_to_irq(u_int apic_id, u_int vector);
void	apic_register_enumerator(struct apic_enumerator *enumerator);
u_int	apic_cpuid(u_int apic_id);
void	*ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase);
int	ioapic_disable_pin(void *cookie, u_int pin);
int	ioapic_get_vector(void *cookie, u_int pin);
void	ioapic_register(void *cookie);
int	ioapic_remap_vector(void *cookie, u_int pin, int vector);
int	ioapic_set_bus(void *cookie, u_int pin, int bus_type);
int	ioapic_set_extint(void *cookie, u_int pin);
int	ioapic_set_nmi(void *cookie, u_int pin);
int	ioapic_set_polarity(void *cookie, u_int pin, enum intr_polarity pol);
int	ioapic_set_triggermode(void *cookie, u_int pin,
	    enum intr_trigger trigger);
int	ioapic_set_smi(void *cookie, u_int pin);
void	lapic_create(u_int apic_id, int boot_cpu);
void	lapic_disable(void);
void	lapic_disable_pmc(void);
void	lapic_dump(const char *str);
void	lapic_enable_cmc(void);
int	lapic_enable_pmc(void);
void	lapic_eoi(void);
int	lapic_id(void);
void	lapic_init(vm_paddr_t addr);
int	lapic_intr_pending(u_int vector);
void	lapic_ipi_raw(register_t icrlo, u_int dest);
void	lapic_ipi_vectored(u_int vector, int dest);
int	lapic_ipi_wait(int delay);
void	lapic_handle_cmc(void);
void	lapic_handle_error(void);
void	lapic_handle_intr(int vector, struct trapframe *frame);
void	lapic_handle_timer(struct trapframe *frame);
void	lapic_reenable_pmc(void);
void	lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id);
int	lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked);
int	lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode);
int	lapic_set_lvt_polarity(u_int apic_id, u_int lvt,
	    enum intr_polarity pol);
int	lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
	    enum intr_trigger trigger);
void	lapic_set_tpr(u_int vector);
void	lapic_setup(int boot);

#endif /* !LOCORE */
#endif /* _MACHINE_APICVAR_H_ */


code:
/*-
 * This file is in the public domain.
 */
/* $FreeBSD: release/9.0.0/sys/amd64/include/apm_bios.h 215140 2010-11-11 19:36:21Z jkim $ */

#include <x86/apm_bios.h>

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * William Jolitz.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)DEFS.h	5.1 (Berkeley) 4/23/90
 * $FreeBSD: release/9.0.0/sys/amd64/include/asm.h 171914 2007-08-22 04:26:07Z jkoshy $
 */

#ifndef _MACHINE_ASM_H_
#define	_MACHINE_ASM_H_

#include <sys/cdefs.h>

#ifdef PIC
#define	PIC_PLT(x)	x@PLT
#define	PIC_GOT(x)	x@GOTPCREL(%rip)
#else
#define	PIC_PLT(x)	x
#define	PIC_GOT(x)	x
#endif

/*
 * CNAME and HIDENAME manage the relationship between symbol names in C
 * and the equivalent assembly language names.  CNAME is given a name as
 * it would be used in a C program.  It expands to the equivalent assembly
 * language name.  HIDENAME is given an assembly-language name, and expands
 * to a possibly-modified form that will be invisible to C programs.
 */
#define CNAME(csym)		csym
#define HIDENAME(asmsym)	.asmsym

#define _START_ENTRY	.text; .p2align 4,0x90

#define _ENTRY(x)	_START_ENTRY; \
			.globl CNAME(x); .type CNAME(x),@function; CNAME(x):

#ifdef PROF
#define	ALTENTRY(x)	_ENTRY(x); \
			pushq %rbp; movq %rsp,%rbp; \
			call PIC_PLT(HIDENAME(mcount)); \
			popq %rbp; \
			jmp 9f
#define	ENTRY(x)	_ENTRY(x); \
			pushq %rbp; movq %rsp,%rbp; \
			call PIC_PLT(HIDENAME(mcount)); \
			popq %rbp; \
			9:
#else
#define	ALTENTRY(x)	_ENTRY(x)
#define	ENTRY(x)	_ENTRY(x)
#endif

#define	END(x)		.size x, . - x

#define RCSID(x)	.text; .asciz x

#undef __FBSDID
#if !defined(lint) && !defined(STRIP_FBSDID)
#define __FBSDID(s)	.ident s
#else
#define __FBSDID(s)	/* nothing */
#endif /* not lint and not STRIP_FBSDID */

#endif /* !_MACHINE_ASM_H_ */


code:
/*-
 * Copyright (c) 1993 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/asmacros.h 209483 2010-06-23 20:44:07Z kib $
 */

#ifndef _MACHINE_ASMACROS_H_
#define _MACHINE_ASMACROS_H_

#include <sys/cdefs.h>

/* XXX too much duplication in various asm*.h's. */

/*
 * CNAME is used to manage the relationship between symbol names in C
 * and the equivalent assembly language names.  CNAME is given a name as
 * it would be used in a C program.  It expands to the equivalent assembly
 * language name.
 */
#define CNAME(csym)		csym

#define ALIGN_DATA	.p2align 3	/* 8 byte alignment, zero filled */
#ifdef GPROF
#define ALIGN_TEXT	.p2align 4,0x90	/* 16-byte alignment, nop filled */
#else
#define ALIGN_TEXT	.p2align 4,0x90	/* 16-byte alignment, nop filled */
#endif
#define SUPERALIGN_TEXT	.p2align 4,0x90	/* 16-byte alignment, nop filled */

#define GEN_ENTRY(name)		ALIGN_TEXT; .globl CNAME(name); \
				.type CNAME(name),@function; CNAME(name):
#define NON_GPROF_ENTRY(name)	GEN_ENTRY(name)
#define NON_GPROF_RET		.byte 0xc3	/* opcode for `ret' */

#define	END(name)		.size name, . - name

#ifdef GPROF
/*
 * __mcount is like [.]mcount except that doesn't require its caller to set
 * up a frame pointer.  It must be called before pushing anything onto the
 * stack.  gcc should eventually generate code to call __mcount in most
 * cases.  This would make -pg in combination with -fomit-frame-pointer
 * useful.  gcc has a configuration variable PROFILE_BEFORE_PROLOGUE to
 * allow profiling before setting up the frame pointer, but this is
 * inadequate for good handling of special cases, e.g., -fpic works best
 * with profiling after the prologue.
 *
 * [.]mexitcount is a new function to support non-statistical profiling if an
 * accurate clock is available.  For C sources, calls to it are generated
 * by the FreeBSD extension `-mprofiler-epilogue' to gcc.  It is best to
 * call [.]mexitcount at the end of a function like the MEXITCOUNT macro does,
 * but gcc currently generates calls to it at the start of the epilogue to
 * avoid problems with -fpic.
 *
 * [.]mcount and __mcount may clobber the call-used registers and %ef.
 * [.]mexitcount may clobber %ecx and %ef.
 *
 * Cross-jumping makes non-statistical profiling timing more complicated.
 * It is handled in many cases by calling [.]mexitcount before jumping.  It
 * is handled for conditional jumps using CROSSJUMP() and CROSSJUMP_LABEL().
 * It is handled for some fault-handling jumps by not sharing the exit
 * routine.
 *
 * ALTENTRY() must be before a corresponding ENTRY() so that it can jump to
 * the main entry point.  Note that alt entries are counted twice.  They
 * have to be counted as ordinary entries for gprof to get the call times
 * right for the ordinary entries.
 *
 * High local labels are used in macros to avoid clashes with local labels
 * in functions.
 *
 * Ordinary `ret' is used instead of a macro `RET' because there are a lot
 * of `ret's.  0xc3 is the opcode for `ret' (`#define ret ... ret' can't
 * be used because this file is sometimes preprocessed in traditional mode).
 * `ret' clobbers eflags but this doesn't matter.
 */
#define ALTENTRY(name)		GEN_ENTRY(name) ; MCOUNT ; MEXITCOUNT ; jmp 9f
#define	CROSSJUMP(jtrue, label, jfalse) \
	jfalse 8f; MEXITCOUNT; jmp __CONCAT(to,label); 8:
#define CROSSJUMPTARGET(label) \
	ALIGN_TEXT; __CONCAT(to,label): ; MCOUNT; jmp label
#define ENTRY(name)		GEN_ENTRY(name) ; 9: ; MCOUNT
#define FAKE_MCOUNT(caller)	pushq caller ; call __mcount ; popq %rcx
#define MCOUNT			call __mcount
#define MCOUNT_LABEL(name)	GEN_ENTRY(name) ; nop ; ALIGN_TEXT
#ifdef GUPROF
#define MEXITCOUNT		call .mexitcount
#define ret			MEXITCOUNT ; NON_GPROF_RET
#else
#define MEXITCOUNT
#endif

#else /* !GPROF */
/*
 * ALTENTRY() has to align because it is before a corresponding ENTRY().
 * ENTRY() has to align to because there may be no ALTENTRY() before it.
 * If there is a previous ALTENTRY() then the alignment code for ENTRY()
 * is empty.
 */
#define ALTENTRY(name)		GEN_ENTRY(name)
#define	CROSSJUMP(jtrue, label, jfalse)	jtrue label
#define	CROSSJUMPTARGET(label)
#define ENTRY(name)		GEN_ENTRY(name)
#define FAKE_MCOUNT(caller)
#define MCOUNT
#define MCOUNT_LABEL(name)
#define MEXITCOUNT
#endif /* GPROF */

#ifdef LOCORE
/*
 * Convenience macro for declaring interrupt entry points.
 */
#define	IDTVEC(name)	ALIGN_TEXT; .globl __CONCAT(X,name); \
			.type __CONCAT(X,name),@function; __CONCAT(X,name):

/*
 * Macros to create and destroy a trap frame.
 */
#define PUSH_FRAME							\
	subq	$TF_RIP,%rsp ;	/* skip dummy tf_err and tf_trapno */	\
	testb	$SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */	\
	jz	1f ;		/* Yes, dont swapgs again */		\
	swapgs ;							\
1:	movq	%rdi,TF_RDI(%rsp) ;					\
	movq	%rsi,TF_RSI(%rsp) ;					\
	movq	%rdx,TF_RDX(%rsp) ;					\
	movq	%rcx,TF_RCX(%rsp) ;					\
	movq	%r8,TF_R8(%rsp) ;					\
	movq	%r9,TF_R9(%rsp) ;					\
	movq	%rax,TF_RAX(%rsp) ;					\
	movq	%rbx,TF_RBX(%rsp) ;					\
	movq	%rbp,TF_RBP(%rsp) ;					\
	movq	%r10,TF_R10(%rsp) ;					\
	movq	%r11,TF_R11(%rsp) ;					\
	movq	%r12,TF_R12(%rsp) ;					\
	movq	%r13,TF_R13(%rsp) ;					\
	movq	%r14,TF_R14(%rsp) ;					\
	movq	%r15,TF_R15(%rsp) ;					\
	movw	%fs,TF_FS(%rsp) ;					\
	movw	%gs,TF_GS(%rsp) ;					\
	movw	%es,TF_ES(%rsp) ;					\
	movw	%ds,TF_DS(%rsp) ;					\
	movl	$TF_HASSEGS,TF_FLAGS(%rsp) ;				\
	cld

#define POP_FRAME							\
	movq	TF_RDI(%rsp),%rdi ;					\
	movq	TF_RSI(%rsp),%rsi ;					\
	movq	TF_RDX(%rsp),%rdx ;					\
	movq	TF_RCX(%rsp),%rcx ;					\
	movq	TF_R8(%rsp),%r8 ;					\
	movq	TF_R9(%rsp),%r9 ;					\
	movq	TF_RAX(%rsp),%rax ;					\
	movq	TF_RBX(%rsp),%rbx ;					\
	movq	TF_RBP(%rsp),%rbp ;					\
	movq	TF_R10(%rsp),%r10 ;					\
	movq	TF_R11(%rsp),%r11 ;					\
	movq	TF_R12(%rsp),%r12 ;					\
	movq	TF_R13(%rsp),%r13 ;					\
	movq	TF_R14(%rsp),%r14 ;					\
	movq	TF_R15(%rsp),%r15 ;					\
	testb	$SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */	\
	jz	1f ;		/* keep kernel GS.base */		\
	cli ;								\
	swapgs ;							\
1:	addq	$TF_RIP,%rsp	/* skip over tf_err, tf_trapno */

/*
 * Access per-CPU data.
 */
#define	PCPU(member)	%gs:PC_ ## member
#define	PCPU_ADDR(member, reg)					\
	movq %gs:PC_PRVSPACE, reg ;				\
	addq $PC_ ## member, reg

#endif /* LOCORE */

#endif /* !_MACHINE_ASMACROS_H_ */


code:
/*-
 * Copyright (c) 1998 Doug Rabson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/atomic.h 216524 2010-12-18 16:41:11Z kib $
 */
#ifndef _MACHINE_ATOMIC_H_
#define	_MACHINE_ATOMIC_H_

#ifndef _SYS_CDEFS_H_
#error this file needs sys/cdefs.h as a prerequisite
#endif

#define	mb()	__asm __volatile("mfence;" : : : "memory")
#define	wmb()	__asm __volatile("sfence;" : : : "memory")
#define	rmb()	__asm __volatile("lfence;" : : : "memory")

/*
 * Various simple operations on memory, each of which is atomic in the
 * presence of interrupts and multiple processors.
 *
 * atomic_set_char(P, V)	(*(u_char *)(P) |= (V))
 * atomic_clear_char(P, V)	(*(u_char *)(P) &= ~(V))
 * atomic_add_char(P, V)	(*(u_char *)(P) += (V))
 * atomic_subtract_char(P, V)	(*(u_char *)(P) -= (V))
 *
 * atomic_set_short(P, V)	(*(u_short *)(P) |= (V))
 * atomic_clear_short(P, V)	(*(u_short *)(P) &= ~(V))
 * atomic_add_short(P, V)	(*(u_short *)(P) += (V))
 * atomic_subtract_short(P, V)	(*(u_short *)(P) -= (V))
 *
 * atomic_set_int(P, V)		(*(u_int *)(P) |= (V))
 * atomic_clear_int(P, V)	(*(u_int *)(P) &= ~(V))
 * atomic_add_int(P, V)		(*(u_int *)(P) += (V))
 * atomic_subtract_int(P, V)	(*(u_int *)(P) -= (V))
 * atomic_readandclear_int(P)	(return (*(u_int *)(P)); *(u_int *)(P) = 0;)
 *
 * atomic_set_long(P, V)	(*(u_long *)(P) |= (V))
 * atomic_clear_long(P, V)	(*(u_long *)(P) &= ~(V))
 * atomic_add_long(P, V)	(*(u_long *)(P) += (V))
 * atomic_subtract_long(P, V)	(*(u_long *)(P) -= (V))
 * atomic_readandclear_long(P)	(return (*(u_long *)(P)); *(u_long *)(P) = 0;)
 */

/*
 * The above functions are expanded inline in the statically-linked
 * kernel.  Lock prefixes are generated if an SMP kernel is being
 * built.
 *
 * Kernel modules call real functions which are built into the kernel.
 * This allows kernel modules to be portable between UP and SMP systems.
 */
#if defined(KLD_MODULE) || !defined(__GNUCLIKE_ASM)
#define	ATOMIC_ASM(NAME, TYPE, OP, CONS, V)			\
void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);	\
void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)

int	atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
int	atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src);
u_int	atomic_fetchadd_int(volatile u_int *p, u_int v);
u_long	atomic_fetchadd_long(volatile u_long *p, u_long v);

#define	ATOMIC_STORE_LOAD(TYPE, LOP, SOP)			\
u_##TYPE	atomic_load_acq_##TYPE(volatile u_##TYPE *p);	\
void		atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)

#else /* !KLD_MODULE && __GNUCLIKE_ASM */

/*
 * For userland, always use lock prefixes so that the binaries will run
 * on both SMP and !SMP systems.
 */
#if defined(SMP) || !defined(_KERNEL)
#define	MPLOCKED	"lock ; "
#else
#define	MPLOCKED
#endif

/*
 * The assembly is volatilized to avoid code chunk removal by the compiler.
 * GCC aggressively reorders operations and memory clobbering is necessary
 * in order to avoid that for memory barriers.
 */
#define	ATOMIC_ASM(NAME, TYPE, OP, CONS, V)		\
static __inline void					\
atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
{							\
	__asm __volatile(MPLOCKED OP			\
	: "=m" (*p)					\
	: CONS (V), "m" (*p)				\
	: "cc");					\
}							\
							\
static __inline void					\
atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
{							\
	__asm __volatile(MPLOCKED OP			\
	: "=m" (*p)					\
	: CONS (V), "m" (*p)				\
	: "memory", "cc");				\
}							\
struct __hack

/*
 * Atomic compare and set, used by the mutex functions
 *
 * if (*dst == expect) *dst = src (all 32 bit words)
 *
 * Returns 0 on failure, non-zero on success
 */

static __inline int
atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
{
	u_char res;

	__asm __volatile(
	"	" MPLOCKED "		"
	"	cmpxchgl %2,%1 ;	"
	"       sete	%0 ;		"
	"1:				"
	"# atomic_cmpset_int"
	: "=a" (res),			/* 0 */
	  "=m" (*dst)			/* 1 */
	: "r" (src),			/* 2 */
	  "a" (expect),			/* 3 */
	  "m" (*dst)			/* 4 */
	: "memory", "cc");

	return (res);
}

static __inline int
atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src)
{
	u_char res;

	__asm __volatile(
	"	" MPLOCKED "		"
	"	cmpxchgq %2,%1 ;	"
	"       sete	%0 ;		"
	"1:				"
	"# atomic_cmpset_long"
	: "=a" (res),			/* 0 */
	  "=m" (*dst)			/* 1 */
	: "r" (src),			/* 2 */
	  "a" (expect),			/* 3 */
	  "m" (*dst)			/* 4 */
	: "memory", "cc");

	return (res);
}

/*
 * Atomically add the value of v to the integer pointed to by p and return
 * the previous value of *p.
 */
static __inline u_int
atomic_fetchadd_int(volatile u_int *p, u_int v)
{

	__asm __volatile(
	"	" MPLOCKED "		"
	"	xaddl	%0, %1 ;	"
	"# atomic_fetchadd_int"
	: "+r" (v),			/* 0 (result) */
	  "=m" (*p)			/* 1 */
	: "m" (*p)			/* 2 */
	: "cc");
	return (v);
}

/*
 * Atomically add the value of v to the long integer pointed to by p and return
 * the previous value of *p.
 */
static __inline u_long
atomic_fetchadd_long(volatile u_long *p, u_long v)
{

	__asm __volatile(
	"	" MPLOCKED "		"
	"	xaddq	%0, %1 ;	"
	"# atomic_fetchadd_long"
	: "+r" (v),			/* 0 (result) */
	  "=m" (*p)			/* 1 */
	: "m" (*p)			/* 2 */
	: "cc");
	return (v);
}

#if defined(_KERNEL) && !defined(SMP)

/*
 * We assume that a = b will do atomic loads and stores.  However, on a
 * PentiumPro or higher, reads may pass writes, so for that case we have
 * to use a serializing instruction (i.e. with LOCK) to do the load in
 * SMP kernels.  For UP kernels, however, the cache of the single processor
 * is always consistent, so we only need to take care of compiler.
 */
#define	ATOMIC_STORE_LOAD(TYPE, LOP, SOP)		\
static __inline u_##TYPE				\
atomic_load_acq_##TYPE(volatile u_##TYPE *p)		\
{							\
	u_##TYPE tmp;					\
							\
	tmp = *p;					\
	__asm __volatile ("" : : : "memory");		\
	return (tmp);					\
}							\
							\
static __inline void					\
atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
{							\
	__asm __volatile ("" : : : "memory");		\
	*p = v;						\
}							\
struct __hack

#else /* !(_KERNEL && !SMP) */

#define	ATOMIC_STORE_LOAD(TYPE, LOP, SOP)		\
static __inline u_##TYPE				\
atomic_load_acq_##TYPE(volatile u_##TYPE *p)		\
{							\
	u_##TYPE res;					\
							\
	__asm __volatile(MPLOCKED LOP			\
	: "=a" (res),			/* 0 */		\
	  "=m" (*p)			/* 1 */		\
	: "m" (*p)			/* 2 */		\
	: "memory", "cc");				\
							\
	return (res);					\
}							\
							\
/*							\
 * The XCHG instruction asserts LOCK automagically.	\
 */							\
static __inline void					\
atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
{							\
	__asm __volatile(SOP				\
	: "=m" (*p),			/* 0 */		\
	  "+r" (v)			/* 1 */		\
	: "m" (*p)			/* 2 */		\
	: "memory");					\
}							\
struct __hack

#endif /* _KERNEL && !SMP */

#endif /* KLD_MODULE || !__GNUCLIKE_ASM */

ATOMIC_ASM(set,	     char,  "orb %b1,%0",  "iq",  v);
ATOMIC_ASM(clear,    char,  "andb %b1,%0", "iq", ~v);
ATOMIC_ASM(add,	     char,  "addb %b1,%0", "iq",  v);
ATOMIC_ASM(subtract, char,  "subb %b1,%0", "iq",  v);

ATOMIC_ASM(set,	     short, "orw %w1,%0",  "ir",  v);
ATOMIC_ASM(clear,    short, "andw %w1,%0", "ir", ~v);
ATOMIC_ASM(add,	     short, "addw %w1,%0", "ir",  v);
ATOMIC_ASM(subtract, short, "subw %w1,%0", "ir",  v);

ATOMIC_ASM(set,	     int,   "orl %1,%0",   "ir",  v);
ATOMIC_ASM(clear,    int,   "andl %1,%0",  "ir", ~v);
ATOMIC_ASM(add,	     int,   "addl %1,%0",  "ir",  v);
ATOMIC_ASM(subtract, int,   "subl %1,%0",  "ir",  v);

ATOMIC_ASM(set,	     long,  "orq %1,%0",   "ir",  v);
ATOMIC_ASM(clear,    long,  "andq %1,%0",  "ir", ~v);
ATOMIC_ASM(add,	     long,  "addq %1,%0",  "ir",  v);
ATOMIC_ASM(subtract, long,  "subq %1,%0",  "ir",  v);

ATOMIC_STORE_LOAD(char,	"cmpxchgb %b0,%1", "xchgb %b1,%0");
ATOMIC_STORE_LOAD(short,"cmpxchgw %w0,%1", "xchgw %w1,%0");
ATOMIC_STORE_LOAD(int,	"cmpxchgl %0,%1",  "xchgl %1,%0");
ATOMIC_STORE_LOAD(long,	"cmpxchgq %0,%1",  "xchgq %1,%0");

#undef ATOMIC_ASM
#undef ATOMIC_STORE_LOAD

#ifndef WANT_FUNCTIONS

/* Read the current value and store a zero in the destination. */
#ifdef __GNUCLIKE_ASM

static __inline u_int
atomic_readandclear_int(volatile u_int *addr)
{
	u_int res;

	res = 0;
	__asm __volatile(
	"	xchgl	%1,%0 ;		"
	"# atomic_readandclear_int"
	: "+r" (res),			/* 0 */
	  "=m" (*addr)			/* 1 */
	: "m" (*addr));

	return (res);
}

static __inline u_long
atomic_readandclear_long(volatile u_long *addr)
{
	u_long res;

	res = 0;
	__asm __volatile(
	"	xchgq	%1,%0 ;		"
	"# atomic_readandclear_long"
	: "+r" (res),			/* 0 */
	  "=m" (*addr)			/* 1 */
	: "m" (*addr));

	return (res);
}

#else /* !__GNUCLIKE_ASM */

u_int	atomic_readandclear_int(volatile u_int *addr);
u_long	atomic_readandclear_long(volatile u_long *addr);

#endif /* __GNUCLIKE_ASM */

#define	atomic_set_acq_char		atomic_set_barr_char
#define	atomic_set_rel_char		atomic_set_barr_char
#define	atomic_clear_acq_char		atomic_clear_barr_char
#define	atomic_clear_rel_char		atomic_clear_barr_char
#define	atomic_add_acq_char		atomic_add_barr_char
#define	atomic_add_rel_char		atomic_add_barr_char
#define	atomic_subtract_acq_char	atomic_subtract_barr_char
#define	atomic_subtract_rel_char	atomic_subtract_barr_char

#define	atomic_set_acq_short		atomic_set_barr_short
#define	atomic_set_rel_short		atomic_set_barr_short
#define	atomic_clear_acq_short		atomic_clear_barr_short
#define	atomic_clear_rel_short		atomic_clear_barr_short
#define	atomic_add_acq_short		atomic_add_barr_short
#define	atomic_add_rel_short		atomic_add_barr_short
#define	atomic_subtract_acq_short	atomic_subtract_barr_short
#define	atomic_subtract_rel_short	atomic_subtract_barr_short

#define	atomic_set_acq_int		atomic_set_barr_int
#define	atomic_set_rel_int		atomic_set_barr_int
#define	atomic_clear_acq_int		atomic_clear_barr_int
#define	atomic_clear_rel_int		atomic_clear_barr_int
#define	atomic_add_acq_int		atomic_add_barr_int
#define	atomic_add_rel_int		atomic_add_barr_int
#define	atomic_subtract_acq_int		atomic_subtract_barr_int
#define	atomic_subtract_rel_int		atomic_subtract_barr_int
#define	atomic_cmpset_acq_int		atomic_cmpset_int
#define	atomic_cmpset_rel_int		atomic_cmpset_int

#define	atomic_set_acq_long		atomic_set_barr_long
#define	atomic_set_rel_long		atomic_set_barr_long
#define	atomic_clear_acq_long		atomic_clear_barr_long
#define	atomic_clear_rel_long		atomic_clear_barr_long
#define	atomic_add_acq_long		atomic_add_barr_long
#define	atomic_add_rel_long		atomic_add_barr_long
#define	atomic_subtract_acq_long	atomic_subtract_barr_long
#define	atomic_subtract_rel_long	atomic_subtract_barr_long
#define	atomic_cmpset_acq_long		atomic_cmpset_long
#define	atomic_cmpset_rel_long		atomic_cmpset_long

/* Operations on 8-bit bytes. */
#define	atomic_set_8		atomic_set_char
#define	atomic_set_acq_8	atomic_set_acq_char
#define	atomic_set_rel_8	atomic_set_rel_char
#define	atomic_clear_8		atomic_clear_char
#define	atomic_clear_acq_8	atomic_clear_acq_char
#define	atomic_clear_rel_8	atomic_clear_rel_char
#define	atomic_add_8		atomic_add_char
#define	atomic_add_acq_8	atomic_add_acq_char
#define	atomic_add_rel_8	atomic_add_rel_char
#define	atomic_subtract_8	atomic_subtract_char
#define	atomic_subtract_acq_8	atomic_subtract_acq_char
#define	atomic_subtract_rel_8	atomic_subtract_rel_char
#define	atomic_load_acq_8	atomic_load_acq_char
#define	atomic_store_rel_8	atomic_store_rel_char

/* Operations on 16-bit words. */
#define	atomic_set_16		atomic_set_short
#define	atomic_set_acq_16	atomic_set_acq_short
#define	atomic_set_rel_16	atomic_set_rel_short
#define	atomic_clear_16		atomic_clear_short
#define	atomic_clear_acq_16	atomic_clear_acq_short
#define	atomic_clear_rel_16	atomic_clear_rel_short
#define	atomic_add_16		atomic_add_short
#define	atomic_add_acq_16	atomic_add_acq_short
#define	atomic_add_rel_16	atomic_add_rel_short
#define	atomic_subtract_16	atomic_subtract_short
#define	atomic_subtract_acq_16	atomic_subtract_acq_short
#define	atomic_subtract_rel_16	atomic_subtract_rel_short
#define	atomic_load_acq_16	atomic_load_acq_short
#define	atomic_store_rel_16	atomic_store_rel_short

/* Operations on 32-bit double words. */
#define	atomic_set_32		atomic_set_int
#define	atomic_set_acq_32	atomic_set_acq_int
#define	atomic_set_rel_32	atomic_set_rel_int
#define	atomic_clear_32		atomic_clear_int
#define	atomic_clear_acq_32	atomic_clear_acq_int
#define	atomic_clear_rel_32	atomic_clear_rel_int
#define	atomic_add_32		atomic_add_int
#define	atomic_add_acq_32	atomic_add_acq_int
#define	atomic_add_rel_32	atomic_add_rel_int
#define	atomic_subtract_32	atomic_subtract_int
#define	atomic_subtract_acq_32	atomic_subtract_acq_int
#define	atomic_subtract_rel_32	atomic_subtract_rel_int
#define	atomic_load_acq_32	atomic_load_acq_int
#define	atomic_store_rel_32	atomic_store_rel_int
#define	atomic_cmpset_32	atomic_cmpset_int
#define	atomic_cmpset_acq_32	atomic_cmpset_acq_int
#define	atomic_cmpset_rel_32	atomic_cmpset_rel_int
#define	atomic_readandclear_32	atomic_readandclear_int
#define	atomic_fetchadd_32	atomic_fetchadd_int

/* Operations on 64-bit quad words. */
#define	atomic_set_64		atomic_set_long
#define	atomic_set_acq_64	atomic_set_acq_long
#define	atomic_set_rel_64	atomic_set_rel_long
#define	atomic_clear_64		atomic_clear_long
#define	atomic_clear_acq_64	atomic_clear_acq_long
#define	atomic_clear_rel_64	atomic_clear_rel_long
#define	atomic_add_64		atomic_add_long
#define	atomic_add_acq_64	atomic_add_acq_long
#define	atomic_add_rel_64	atomic_add_rel_long
#define	atomic_subtract_64	atomic_subtract_long
#define	atomic_subtract_acq_64	atomic_subtract_acq_long
#define	atomic_subtract_rel_64	atomic_subtract_rel_long
#define	atomic_load_acq_64	atomic_load_acq_long
#define	atomic_store_rel_64	atomic_store_rel_long
#define	atomic_cmpset_64	atomic_cmpset_long
#define	atomic_cmpset_acq_64	atomic_cmpset_acq_long
#define	atomic_cmpset_rel_64	atomic_cmpset_rel_long
#define	atomic_readandclear_64	atomic_readandclear_long

/* Operations on pointers. */
#define	atomic_set_ptr		atomic_set_long
#define	atomic_set_acq_ptr	atomic_set_acq_long
#define	atomic_set_rel_ptr	atomic_set_rel_long
#define	atomic_clear_ptr	atomic_clear_long
#define	atomic_clear_acq_ptr	atomic_clear_acq_long
#define	atomic_clear_rel_ptr	atomic_clear_rel_long
#define	atomic_add_ptr		atomic_add_long
#define	atomic_add_acq_ptr	atomic_add_acq_long
#define	atomic_add_rel_ptr	atomic_add_rel_long
#define	atomic_subtract_ptr	atomic_subtract_long
#define	atomic_subtract_acq_ptr	atomic_subtract_acq_long
#define	atomic_subtract_rel_ptr	atomic_subtract_rel_long
#define	atomic_load_acq_ptr	atomic_load_acq_long
#define	atomic_store_rel_ptr	atomic_store_rel_long
#define	atomic_cmpset_ptr	atomic_cmpset_long
#define	atomic_cmpset_acq_ptr	atomic_cmpset_acq_long
#define	atomic_cmpset_rel_ptr	atomic_cmpset_rel_long
#define	atomic_readandclear_ptr	atomic_readandclear_long

#endif /* !WANT_FUNCTIONS */

#endif /* !_MACHINE_ATOMIC_H_ */


code:
/*-
 * This file is in the public domain.
 */
/* $FreeBSD: release/9.0.0/sys/amd64/include/bus.h 216592 2010-12-20 16:39:43Z tijl $ */

#include <x86/bus.h>


code:
/*-
 * Copyright (c) 2005 Scott Long
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/bus_dma.h 148275 2005-07-22 04:03:25Z obrien $
 */

#ifndef _AMD64_BUS_DMA_H_
#define _AMD64_BUS_DMA_H_

#include <sys/bus_dma.h>

#endif /* _AMD64_BUS_DMA_H_ */


code:
/*-
 * Kernel interface to machine-dependent clock driver.
 * Garrett Wollman, September 1994.
 * This file is in the public domain.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/clock.h 221703 2011-05-09 17:34:00Z jkim $
 */

#ifndef _MACHINE_CLOCK_H_
#define	_MACHINE_CLOCK_H_

#ifdef _KERNEL
/*
 * i386 to clock driver interface.
 * XXX large parts of the driver and its interface are misplaced.
 */
extern int	clkintr_pending;
extern u_int	i8254_freq;
extern int	i8254_max_count;
extern uint64_t	tsc_freq;
extern int	tsc_is_invariant;
extern int	tsc_perf_stat;

void	i8254_init(void);

/*
 * Driver to clock driver interface.
 */

void	startrtclock(void);
void	init_TSC(void);

#define	HAS_TIMER_SPKR 1
int	timer_spkr_acquire(void);
int	timer_spkr_release(void);
void	timer_spkr_setfreq(int freq);

#endif /* _KERNEL */

#endif /* !_MACHINE_CLOCK_H_ */


code:
/*-
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * William Jolitz.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)cpu.h	5.4 (Berkeley) 5/9/91
 * $FreeBSD: release/9.0.0/sys/amd64/include/cpu.h 219673 2011-03-15 17:19:52Z jkim $
 */

#ifndef _MACHINE_CPU_H_
#define	_MACHINE_CPU_H_

/*
 * Definitions unique to i386 cpu support.
 */
#include <machine/psl.h>
#include <machine/frame.h>
#include <machine/segments.h>

#define	cpu_exec(p)	/* nothing */
#define	cpu_swapin(p)	/* nothing */
#define	cpu_getstack(td)		((td)->td_frame->tf_rsp)
#define	cpu_setstack(td, ap)		((td)->td_frame->tf_rsp = (ap))
#define	cpu_spinwait()			ia32_pause()

#define	TRAPF_USERMODE(framep) \
	(ISPL((framep)->tf_cs) == SEL_UPL)
#define	TRAPF_PC(framep)	((framep)->tf_rip)

#ifdef _KERNEL
extern char	btext[];
extern char	etext[];

void	cpu_halt(void);
void	cpu_reset(void);
void	fork_trampoline(void);
void	swi_vm(void *);

/*
 * Return contents of in-cpu fast counter as a sort of "bogo-time"
 * for random-harvesting purposes.
 */
static __inline u_int64_t
get_cyclecount(void)
{

	return (rdtsc());
}

#endif

#endif /* !_MACHINE_CPU_H_ */


code:
///*-
// * Copyright (c) 2003 Peter Wemm.
// * Copyright (c) 1993 The Regents of the University of California.
// * All rights reserved.
// *
// * Redistribution and use in source and binary forms, with or without
// * modification, are permitted provided that the following conditions
// * are met:
// * 1. Redistributions of source code must retain the above copyright
// *    notice, this list of conditions and the following disclaimer.
// * 2. Redistributions in binary form must reproduce the above copyright
// *    notice, this list of conditions and the following disclaimer in the
// *    documentation and/or other materials provided with the distribution.
// * 4. Neither the name of the University nor the names of its contributors
// *    may be used to endorse or promote products derived from this software
// *    without specific prior written permission.
// *
// * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
// * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
// * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// * SUCH DAMAGE.
// *
// * $FreeBSD: release/9.0.0/sys/amd64/include/cpufunc.h 223796 2011-07-05 18:42:10Z jkim $
// */
//
///*
// * Functions to provide access to special i386 instructions.
// * This in included in sys/systm.h, and that file should be
// * used in preference to this.
// */
//
//#ifndef _MACHINE_CPUFUNC_H_
//#define	_MACHINE_CPUFUNC_H_
//
//#ifndef _SYS_CDEFS_H_
//#error this file needs sys/cdefs.h as a prerequisite
//#endif
//
//struct region_descriptor;
//
//#define readb(va)	(*(volatile uint8_t *) (va))
//#define readw(va)	(*(volatile uint16_t *) (va))
//#define readl(va)	(*(volatile uint32_t *) (va))
//#define readq(va)	(*(volatile uint64_t *) (va))
//
//#define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
//#define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
//#define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
//#define writeq(va, d)	(*(volatile uint64_t *) (va) = (d))
//
//#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
//
//static __inline void
//breakpoint(void)
//{
//	__asm __volatile("int $3");
//}
//
//static __inline u_int
//bsfl(u_int mask)
//{
//	u_int	result;
//
//	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
//	return (result);
//}
//
//static __inline u_long
//bsfq(u_long mask)
//{
//	u_long	result;
//
//	__asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask));
//	return (result);
//}
//
//static __inline u_int
//bsrl(u_int mask)
//{
//	u_int	result;
//
//	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
//	return (result);
//}
//
//static __inline u_long
//bsrq(u_long mask)
//{
//	u_long	result;
//
//	__asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask));
//	return (result);
//}
//
//static __inline void
//clflush(u_long addr)
//{
//
//	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
//}
//
//static __inline void
//disable_intr(void)
//{
//	__asm __volatile("cli" : : : "memory");
//}
//
//static __inline void
//do_cpuid(u_int ax, u_int *p)
//{
//	__asm __volatile("cpuid"
//			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
//			 :  "0" (ax));
//}
//
//static __inline void
//cpuid_count(u_int ax, u_int cx, u_int *p)
//{
//	__asm __volatile("cpuid"
//			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
//			 :  "0" (ax), "c" (cx));
//}
//
//static __inline void
//enable_intr(void)
//{
//	__asm __volatile("sti");
//}
//
//#ifdef _KERNEL
//
//#define	HAVE_INLINE_FFS
//#define        ffs(x)  __builtin_ffs(x)
//
//#define	HAVE_INLINE_FFSL
//
//static __inline int
//ffsl(long mask)
//{
//	return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1);
//}
//
//#define	HAVE_INLINE_FLS
//
//static __inline int
//fls(int mask)
//{
//	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
//}
//
//#define	HAVE_INLINE_FLSL
//
//static __inline int
//flsl(long mask)
//{
//	return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
//}
//
//#endif /* _KERNEL */
//
//static __inline void
//halt(void)
//{
//	__asm __volatile("hlt");
//}
//
//static __inline u_char
//inb(u_int port)
//{
//	u_char	data;
//
//	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
//	return (data);
//}
//
//static __inline u_int
//inl(u_int port)
//{
//	u_int	data;
//
//	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
//	return (data);
//}
//
//static __inline void
//insb(u_int port, void *addr, size_t count)
//{
//	__asm __volatile("cld; rep; insb"
//			 : "+D" (addr), "+c" (count)
//			 : "d" (port)
//			 : "memory");
//}
//
//static __inline void
//insw(u_int port, void *addr, size_t count)
//{
//	__asm __volatile("cld; rep; insw"
//			 : "+D" (addr), "+c" (count)
//			 : "d" (port)
//			 : "memory");
//}
//
//static __inline void
//insl(u_int port, void *addr, size_t count)
//{
//	__asm __volatile("cld; rep; insl"
//			 : "+D" (addr), "+c" (count)
//			 : "d" (port)
//			 : "memory");
//}
//
//static __inline void
//invd(void)
//{
//	__asm __volatile("invd");
//}
//
//static __inline u_short
//inw(u_int port)
//{
//	u_short	data;
//
//	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
//	return (data);
//}
//
//static __inline void
//outb(u_int port, u_char data)
//{
//	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
//}
//
//static __inline void
//outl(u_int port, u_int data)
//{
//	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
//}
//
//static __inline void
//outsb(u_int port, const void *addr, size_t count)
//{
//	__asm __volatile("cld; rep; outsb"
//			 : "+S" (addr), "+c" (count)
//			 : "d" (port));
//}
//
//static __inline void
//outsw(u_int port, const void *addr, size_t count)
//{
//	__asm __volatile("cld; rep; outsw"
//			 : "+S" (addr), "+c" (count)
//			 : "d" (port));
//}
//
//static __inline void
//outsl(u_int port, const void *addr, size_t count)
//{
//	__asm __volatile("cld; rep; outsl"
//			 : "+S" (addr), "+c" (count)
//			 : "d" (port));
//}
//
//static __inline void
//outw(u_int port, u_short data)
//{
//	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
//}
//
//static __inline void
//mfence(void)
//{
//
//	__asm __volatile("mfence" : : : "memory");
//}
//
//static __inline void
//ia32_pause(void)
//{
//	__asm __volatile("pause");
//}
//
//static __inline u_long
//read_rflags(void)
//{
//	u_long	rf;
//
//	__asm __volatile("pushfq; popq %0" : "=r" (rf));
//	return (rf);
//}
//
//static __inline uint64_t
//rdmsr(u_int msr)
//{
//	uint32_t low, high;
//
//	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
//	return (low | ((uint64_t)high << 32));
//}
//
//static __inline uint64_t
//rdpmc(u_int pmc)
//{
//	uint32_t low, high;
//
//	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
//	return (low | ((uint64_t)high << 32));
//}
//
//static __inline uint64_t
//rdtsc(void)
//{
//	uint32_t low, high;
//
//	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
//	return (low | ((uint64_t)high << 32));
//}
//
//static __inline uint32_t
//rdtsc32(void)
//{
//	uint32_t rv;
//
//	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
//	return (rv);
//}
//
//static __inline void
//wbinvd(void)
//{
//	__asm __volatile("wbinvd");
//}
//
//static __inline void
//write_rflags(u_long rf)
//{
//	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
//}
//
//static __inline void
//wrmsr(u_int msr, uint64_t newval)
//{
//	uint32_t low, high;
//
//	low = newval;
//	high = newval >> 32;
//	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
//}
//
//static __inline void
//load_cr0(u_long data)
//{
//
//	__asm __volatile("movq %0,%%cr0" : : "r" (data));
//}
//
//static __inline u_long
//rcr0(void)
//{
//	u_long	data;
//
//	__asm __volatile("movq %%cr0,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline u_long
//rcr2(void)
//{
//	u_long	data;
//
//	__asm __volatile("movq %%cr2,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_cr3(u_long data)
//{
//
//	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
//}
//
//static __inline u_long
//rcr3(void)
//{
//	u_long	data;
//
//	__asm __volatile("movq %%cr3,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_cr4(u_long data)
//{
//	__asm __volatile("movq %0,%%cr4" : : "r" (data));
//}
//
//static __inline u_long
//rcr4(void)
//{
//	u_long	data;
//
//	__asm __volatile("movq %%cr4,%0" : "=r" (data));
//	return (data);
//}
//
///*
// * Global TLB flush (except for thise for pages marked PG_G)
// */
//static __inline void
//invltlb(void)
//{
//
//	load_cr3(rcr3());
//}
//
///*
// * TLB flush for an individual page (even if it has PG_G).
// * Only works on 486+ CPUs (i386 does not have PG_G).
// */
//static __inline void
//invlpg(u_long addr)
//{
//
//	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
//}
//
//static __inline u_short
//rfs(void)
//{
//	u_short sel;
//	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
//	return (sel);
//}
//
//static __inline u_short
//rgs(void)
//{
//	u_short sel;
//	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
//	return (sel);
//}
//
//static __inline u_short
//rss(void)
//{
//	u_short sel;
//	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
//	return (sel);
//}
//
//static __inline void
//load_ds(u_short sel)
//{
//	__asm __volatile("movw %0,%%ds" : : "rm" (sel));
//}
//
//static __inline void
//load_es(u_short sel)
//{
//	__asm __volatile("movw %0,%%es" : : "rm" (sel));
//}
//
//static __inline void
//cpu_monitor(const void *addr, u_long extensions, u_int hints)
//{
//
//	__asm __volatile("monitor"
//	    : : "a" (addr), "c" (extensions), "d" (hints));
//}
//
//static __inline void
//cpu_mwait(u_long extensions, u_int hints)
//{
//
//	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
//}
//
//#ifdef _KERNEL
///* This is defined in <machine/specialreg.h> but is too painful to get to */
//#ifndef	MSR_FSBASE
//#define	MSR_FSBASE	0xc0000100
//#endif
//static __inline void
//load_fs(u_short sel)
//{
//	/* Preserve the fsbase value across the selector load */
//	__asm __volatile("rdmsr; movw %0,%%fs; wrmsr"
//	    : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
//}
//
//#ifndef	MSR_GSBASE
//#define	MSR_GSBASE	0xc0000101
//#endif
//static __inline void
//load_gs(u_short sel)
//{
//	/*
//	 * Preserve the gsbase value across the selector load.
//	 * Note that we have to disable interrupts because the gsbase
//	 * being trashed happens to be the kernel gsbase at the time.
//	 */
//	__asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
//	    : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
//}
//#else
///* Usable by userland */
//static __inline void
//load_fs(u_short sel)
//{
//	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
//}
//
//static __inline void
//load_gs(u_short sel)
//{
//	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
//}
//#endif
//
//static __inline void
//lidt(struct region_descriptor *addr)
//{
//	__asm __volatile("lidt (%0)" : : "r" (addr));
//}
//
//static __inline void
//lldt(u_short sel)
//{
//	__asm __volatile("lldt %0" : : "r" (sel));
//}
//
//static __inline void
//ltr(u_short sel)
//{
//	__asm __volatile("ltr %0" : : "r" (sel));
//}
//
//static __inline uint64_t
//rdr0(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr0,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr0(uint64_t dr0)
//{
//	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
//}
//
//static __inline uint64_t
//rdr1(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr1,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr1(uint64_t dr1)
//{
//	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
//}
//
//static __inline uint64_t
//rdr2(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr2,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr2(uint64_t dr2)
//{
//	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
//}
//
//static __inline uint64_t
//rdr3(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr3,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr3(uint64_t dr3)
//{
//	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
//}
//
//static __inline uint64_t
//rdr4(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr4,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr4(uint64_t dr4)
//{
//	__asm __volatile("movq %0,%%dr4" : : "r" (dr4));
//}
//
//static __inline uint64_t
//rdr5(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr5,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr5(uint64_t dr5)
//{
//	__asm __volatile("movq %0,%%dr5" : : "r" (dr5));
//}
//
//static __inline uint64_t
//rdr6(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr6,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr6(uint64_t dr6)
//{
//	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
//}
//
//static __inline uint64_t
//rdr7(void)
//{
//	uint64_t data;
//	__asm __volatile("movq %%dr7,%0" : "=r" (data));
//	return (data);
//}
//
//static __inline void
//load_dr7(uint64_t dr7)
//{
//	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
//}
//
//static __inline register_t
//intr_disable(void)
//{
//	register_t rflags;
//
//	rflags = read_rflags();
//	disable_intr();
//	return (rflags);
//}
//
//static __inline void
//intr_restore(register_t rflags)
//{
//	write_rflags(rflags);
//}
//
//#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
//
//int	breakpoint(void);
//u_int	bsfl(u_int mask);
//u_int	bsrl(u_int mask);
//void	disable_intr(void);
//void	do_cpuid(u_int ax, u_int *p);
//void	enable_intr(void);
//void	halt(void);
//void	ia32_pause(void);
//u_char	inb(u_int port);
//u_int	inl(u_int port);
//void	insb(u_int port, void *addr, size_t count);
//void	insl(u_int port, void *addr, size_t count);
//void	insw(u_int port, void *addr, size_t count);
//register_t	intr_disable(void);
//void	intr_restore(register_t rf);
//void	invd(void);
//void	invlpg(u_int addr);
//void	invltlb(void);
//u_short	inw(u_int port);
//void	lidt(struct region_descriptor *addr);
//void	lldt(u_short sel);
//void	load_cr0(u_long cr0);
//void	load_cr3(u_long cr3);
//void	load_cr4(u_long cr4);
//void	load_dr0(uint64_t dr0);
//void	load_dr1(uint64_t dr1);
//void	load_dr2(uint64_t dr2);
//void	load_dr3(uint64_t dr3);
//void	load_dr4(uint64_t dr4);
//void	load_dr5(uint64_t dr5);
//void	load_dr6(uint64_t dr6);
//void	load_dr7(uint64_t dr7);
//void	load_fs(u_short sel);
//void	load_gs(u_short sel);
//void	ltr(u_short sel);
//void	outb(u_int port, u_char data);
//void	outl(u_int port, u_int data);
//void	outsb(u_int port, const void *addr, size_t count);
//void	outsl(u_int port, const void *addr, size_t count);
//void	outsw(u_int port, const void *addr, size_t count);
//void	outw(u_int port, u_short data);
//u_long	rcr0(void);
//u_long	rcr2(void);
//u_long	rcr3(void);
//u_long	rcr4(void);
//uint64_t rdmsr(u_int msr);
//uint64_t rdpmc(u_int pmc);
//uint64_t rdr0(void);
//uint64_t rdr1(void);
//uint64_t rdr2(void);
//uint64_t rdr3(void);
//uint64_t rdr4(void);
//uint64_t rdr5(void);
//uint64_t rdr6(void);
//uint64_t rdr7(void);
//uint64_t rdtsc(void);
//u_int	read_rflags(void);
//u_int	rfs(void);
//u_int	rgs(void);
//void	wbinvd(void);
//void	write_rflags(u_int rf);
//void	wrmsr(u_int msr, uint64_t newval);
//
//#endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
//
//void	reset_dbregs(void);
//
//#ifdef _KERNEL
//int	rdmsr_safe(u_int msr, uint64_t *val);
//int	wrmsr_safe(u_int msr, uint64_t newval);
//#endif
//
//#endif /* !_MACHINE_CPUFUNC_H_ */


code:
/*-
 * Copyright (c) 1993 Christopher G. Demetriou
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/cputypes.h 186797 2009-01-05 21:51:49Z jkim $
 */

#ifndef _MACHINE_CPUTYPES_H_
#define	_MACHINE_CPUTYPES_H_

/*
 * Classes of processor.
 */
#define	CPUCLASS_X86		0	/* X86 */
#define	CPUCLASS_K8		1	/* K8 AMD64 class */

/*
 * Kinds of processor.
 */
#define	CPU_X86			0	/* Intel */
#define	CPU_CLAWHAMMER		1	/* AMD Clawhammer */
#define	CPU_SLEDGEHAMMER	2	/* AMD Sledgehammer */

/*
 * Vendors of processor.
 */
#define	CPU_VENDOR_AMD		0x1022		/* AMD */
#define	CPU_VENDOR_IDT		0x111d		/* Centaur/IDT/VIA */
#define	CPU_VENDOR_INTEL	0x8086		/* Intel */
#define	CPU_VENDOR_CENTAUR	CPU_VENDOR_IDT

#ifndef LOCORE
extern int	cpu;
extern int	cpu_class;
#endif

#endif /* !_MACHINE_CPUTYPES_H_ */


code:
/*-
 * Mach Operating System
 * Copyright (c) 1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/db_machdep.h 139731 2005-01-05 20:17:21Z imp $
 */

#ifndef _MACHINE_DB_MACHDEP_H_
#define	_MACHINE_DB_MACHDEP_H_

#include <machine/frame.h>
#include <machine/trap.h>

typedef	vm_offset_t	db_addr_t;	/* address - unsigned */
typedef	long		db_expr_t;	/* expression - signed */

#define	PC_REGS()	((db_addr_t)kdb_thrctx->pcb_rip)

#define	BKPT_INST	0xcc		/* breakpoint instruction */
#define	BKPT_SIZE	(1)		/* size of breakpoint inst */
#define	BKPT_SET(inst)	(BKPT_INST)

#define BKPT_SKIP				\
do {						\
	kdb_frame->tf_rip += 1;			\
	kdb_thrctx->pcb_rip += 1;		\
} while(0)

#define	FIXUP_PC_AFTER_BREAK			\
do {						\
	kdb_frame->tf_rip -= 1;			\
	kdb_thrctx->pcb_rip -= 1;		\
} while(0);

#define	db_clear_single_step	kdb_cpu_clear_singlestep
#define	db_set_single_step	kdb_cpu_set_singlestep

#define	IS_BREAKPOINT_TRAP(type, code)	((type) == T_BPTFLT)
/*
 * Watchpoints are not supported.  The debug exception type is in %dr6
 * and not yet in the args to this macro.
 */
#define IS_WATCHPOINT_TRAP(type, code)	0

#define	I_CALL		0xe8
#define	I_CALLI		0xff
#define	I_RET		0xc3
#define	I_IRET		0xcf

#define	inst_trap_return(ins)	(((ins)&0xff) == I_IRET)
#define	inst_return(ins)	(((ins)&0xff) == I_RET)
#define	inst_call(ins)		(((ins)&0xff) == I_CALL || \
				 (((ins)&0xff) == I_CALLI && \
				  ((ins)&0x3800) == 0x1000))
#define inst_load(ins)		0
#define inst_store(ins)		0

/*
 * There no interesting addresses below _kstack = 0xefbfe000.  There
 * are small absolute values for GUPROF, but we don't want to see them.
 * Treat "negative" addresses below _kstack as non-small to allow for
 * future reductions of _kstack and to avoid sign extension problems.
 *
 * There is one interesting symbol above -db_maxoff = 0xffff0000,
 * namely _APTD = 0xfffff000.  Accepting this would mess up the
 * printing of small negative offsets.  The next largest symbol is
 * _APTmap = 0xffc00000.  Accepting this is OK (unless db_maxoff is
 * set to >= 0x400000 - (max stack offset)).
 */
#define	DB_SMALL_VALUE_MAX	0x7fffffff
#define	DB_SMALL_VALUE_MIN	(-0x400001)

#endif /* !_MACHINE_DB_MACHDEP_H_ */


code:
/*-
 * Copyright (c) 1996-1997 John D. Polstra.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/elf.h 217097 2011-01-07 14:22:34Z kib $
 */

#ifndef _MACHINE_ELF_H_
#define	_MACHINE_ELF_H_ 1

/*
 * ELF definitions for the AMD64 architecture.
 */

#ifndef __ELF_WORD_SIZE
#define	__ELF_WORD_SIZE	64	/* Used by <sys/elf_generic.h> */
#endif
#include <sys/elf32.h>	/* Definitions common to all 32 bit architectures. */
#include <sys/elf64.h>	/* Definitions common to all 64 bit architectures. */
#include <sys/elf_generic.h>

#define	ELF_ARCH	EM_X86_64
#define	ELF_ARCH32	EM_386

#define	ELF_MACHINE_OK(x) ((x) == EM_X86_64)

/*
 * Auxiliary vector entries for passing information to the interpreter.
 *
 * The i386 supplement to the SVR4 ABI specification names this "auxv_t",
 * but POSIX lays claim to all symbols ending with "_t".
 */
typedef struct {	/* Auxiliary vector entry on initial stack */
	int	a_type;			/* Entry type. */
	union {
		int	a_val;		/* Integer value. */
	} a_un;
} Elf32_Auxinfo;

typedef struct {	/* Auxiliary vector entry on initial stack */
	long	a_type;			/* Entry type. */
	union {
		long	a_val;		/* Integer value. */
		void	*a_ptr;		/* Address. */
		void	(*a_fcn)(void);	/* Function pointer (not used). */
	} a_un;
} Elf64_Auxinfo;

__ElfType(Auxinfo);

/* Values for a_type. */
#define	AT_NULL		0	/* Terminates the vector. */
#define	AT_IGNORE	1	/* Ignored entry. */
#define	AT_EXECFD	2	/* File descriptor of program to load. */
#define	AT_PHDR		3	/* Program header of program already loaded. */
#define	AT_PHENT	4	/* Size of each program header entry. */
#define	AT_PHNUM	5	/* Number of program header entries. */
#define	AT_PAGESZ	6	/* Page size in bytes. */
#define	AT_BASE		7	/* Interpreter's base address. */
#define	AT_FLAGS	8	/* Flags (unused for i386). */
#define	AT_ENTRY	9	/* Where interpreter should transfer control. */
#define	AT_NOTELF	10	/* Program is not ELF ?? */
#define	AT_UID		11	/* Real uid. */
#define	AT_EUID		12	/* Effective uid. */
#define	AT_GID		13	/* Real gid. */
#define	AT_EGID		14	/* Effective gid. */
#define	AT_EXECPATH	15	/* Path to the executable. */
#define	AT_CANARY	16	/* Canary for SSP */
#define	AT_CANARYLEN	17	/* Length of the canary. */
#define	AT_OSRELDATE	18	/* OSRELDATE. */
#define	AT_NCPUS	19	/* Number of CPUs. */
#define	AT_PAGESIZES	20	/* Pagesizes. */
#define	AT_PAGESIZESLEN	21	/* Number of pagesizes. */
#define	AT_STACKPROT	23	/* Initial stack protection. */

#define	AT_COUNT	24	/* Count of defined aux entry types. */

/*
 * Relocation types.
 */

#define	R_X86_64_COUNT	24	/* Count of defined relocation types. */

/* Define "machine" characteristics */
#if __ELF_WORD_SIZE == 32
#define ELF_TARG_CLASS  ELFCLASS32
#else
#define ELF_TARG_CLASS  ELFCLASS64
#endif
#define	ELF_TARG_DATA	ELFDATA2LSB
#define	ELF_TARG_MACH	EM_X86_64
#define	ELF_TARG_VER	1

#if __ELF_WORD_SIZE == 32
#define	ET_DYN_LOAD_ADDR 0x01001000
#else
#define	ET_DYN_LOAD_ADDR 0x01021000
#endif

#endif /* !_MACHINE_ELF_H_ */


code:
/*-
 * Copyright (c) 1987, 1991 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)endian.h	7.8 (Berkeley) 4/3/91
 * $FreeBSD: release/9.0.0/sys/amd64/include/endian.h 219819 2011-03-21 09:40:01Z jeff $
 */

#ifndef _MACHINE_ENDIAN_H_
#define	_MACHINE_ENDIAN_H_

#include <sys/cdefs.h>
#include <sys/_types.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Define the order of 32-bit words in 64-bit words.
 */
#define	_QUAD_HIGHWORD 1
#define	_QUAD_LOWWORD 0

/*
 * Definitions for byte order, according to byte significance from low
 * address to high.
 */
#define	_LITTLE_ENDIAN	1234	/* LSB first: i386, vax */
#define	_BIG_ENDIAN	4321	/* MSB first: 68000, ibm, net */
#define	_PDP_ENDIAN	3412	/* LSB first in word, MSW first in long */

#define	_BYTE_ORDER	_LITTLE_ENDIAN

/*
 * Deprecated variants that don't have enough underscores to be useful in more
 * strict namespaces.
 */
#if __BSD_VISIBLE
#define	LITTLE_ENDIAN	_LITTLE_ENDIAN
#define	BIG_ENDIAN	_BIG_ENDIAN
#define	PDP_ENDIAN	_PDP_ENDIAN
#define	BYTE_ORDER	_BYTE_ORDER
#endif

#if defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE_BUILTIN_CONSTANT_P)

#define	__bswap64_const(_x)			\
	(((_x) >> 56) |				\
	(((_x) >> 40) & (0xffUL << 8)) |	\
	(((_x) >> 24) & (0xffUL << 16)) |	\
	(((_x) >> 8) & (0xffUL << 24)) |	\
	(((_x) << 8) & (0xffUL << 32)) |	\
	(((_x) << 24) & (0xffUL << 40)) |	\
	(((_x) << 40) & (0xffUL << 48)) |	\
	((_x) << 56))

#define	__bswap32_const(_x)			\
	(((_x) >> 24) |				\
	(((_x) & (0xff << 16)) >> 8) |		\
	(((_x) & (0xff << 8)) << 8) |		\
	((_x) << 24))

#define __bswap16_const(_x)	(__uint16_t)((_x) << 8 | (_x) >> 8)

static __inline __uint64_t
__bswap64_var(__uint64_t _x)
{

	__asm ("bswap %0" : "+r" (_x));
	return (_x);
}

static __inline __uint32_t
__bswap32_var(__uint32_t _x)
{

	__asm ("bswap %0" : "+r" (_x));
	return (_x);
}

static __inline __uint16_t
__bswap16_var(__uint16_t _x)
{

	return (__bswap16_const(_x));
}

#define	__bswap64(_x)					\
	(__builtin_constant_p(_x) ?			\
	    __bswap64_const((__uint64_t)(_x)) : __bswap64_var(_x))

#define	__bswap32(_x)					\
	(__builtin_constant_p(_x) ?			\
	    __bswap32_const((__uint32_t)(_x)) : __bswap32_var(_x))

#define	__bswap16(_x)					\
	(__builtin_constant_p(_x) ?			\
	    __bswap16_const((__uint16_t)(_x)) : __bswap16_var(_x))

#define	__htonl(x)	__bswap32(x)
#define	__htons(x)	__bswap16(x)
#define	__ntohl(x)	__bswap32(x)
#define	__ntohs(x)	__bswap16(x)

#else /* !(__GNUCLIKE_ASM && __GNUCLIKE_BUILTIN_CONSTANT_P) */

/*
 * No optimizations are available for this compiler.  Fall back to
 * non-optimized functions by defining the constant usually used to prevent
 * redefinition.
 */
#define	_BYTEORDER_FUNC_DEFINED

#endif /* __GNUCLIKE_ASM && __GNUCLIKE_BUILTIN_CONSTANT_P */

#ifdef __cplusplus
}
#endif

#endif /* !_MACHINE_ENDIAN_H_ */


code:
/*-
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)exec.h	8.1 (Berkeley) 6/11/93
 * $FreeBSD: release/9.0.0/sys/amd64/include/exec.h 142107 2005-02-19 21:16:48Z ru $
 */

#ifndef	_MACHINE_EXEC_H_
#define	_MACHINE_EXEC_H_

#define	__LDPGSZ	4096

#endif /* !_MACHINE_EXEC_H_ */


code:
/*-
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)float.h	7.1 (Berkeley) 5/8/90
 * $FreeBSD: release/9.0.0/sys/amd64/include/float.h 175398 2008-01-17 13:12:46Z bde $
 */

#ifndef _MACHINE_FLOAT_H_
#define _MACHINE_FLOAT_H_ 1

#include <sys/cdefs.h>

__BEGIN_DECLS
extern int __flt_rounds(void);
__END_DECLS

#define FLT_RADIX	2		/* b */
#define FLT_ROUNDS	__flt_rounds()
#if __ISO_C_VISIBLE >= 1999
#define	FLT_EVAL_METHOD	0		/* no promotions */
#define	DECIMAL_DIG	21		/* max precision in decimal digits */
#endif

#define FLT_MANT_DIG	24		/* p */
#define FLT_EPSILON	1.19209290E-07F	/* b**(1-p) */
#define FLT_DIG		6		/* floor((p-1)*log10(b))+(b == 10) */
#define FLT_MIN_EXP	(-125)		/* emin */
#define FLT_MIN		1.17549435E-38F	/* b**(emin-1) */
#define FLT_MIN_10_EXP	(-37)		/* ceil(log10(b**(emin-1))) */
#define FLT_MAX_EXP	128		/* emax */
#define FLT_MAX		3.40282347E+38F	/* (1-b**(-p))*b**emax */
#define FLT_MAX_10_EXP	38		/* floor(log10((1-b**(-p))*b**emax)) */

#define DBL_MANT_DIG	53
#define DBL_EPSILON	2.2204460492503131E-16
#define DBL_DIG		15
#define DBL_MIN_EXP	(-1021)
#define DBL_MIN		2.2250738585072014E-308
#define DBL_MIN_10_EXP	(-307)
#define DBL_MAX_EXP	1024
#define DBL_MAX		1.7976931348623157E+308
#define DBL_MAX_10_EXP	308

#define LDBL_MANT_DIG	64
#define LDBL_EPSILON	1.0842021724855044340E-19L
#define LDBL_DIG	18
#define LDBL_MIN_EXP	(-16381)
#define LDBL_MIN	3.3621031431120935063E-4932L
#define LDBL_MIN_10_EXP	(-4931)
#define LDBL_MAX_EXP	16384
#define LDBL_MAX	1.1897314953572317650E+4932L
#define LDBL_MAX_10_EXP	4932
#endif /* _MACHINE_FLOAT_H_ */


code:
/*-
 * Copyright (c) 1993 Andrew Moore, Talke Studio
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#) floatingpoint.h	1.0 (Berkeley) 9/23/93
 * $FreeBSD: release/9.0.0/sys/amd64/include/floatingpoint.h 144544 2005-04-02 17:31:42Z netchild $
 */

#ifndef _FLOATINGPOINT_H_
#define _FLOATINGPOINT_H_

#include <sys/cdefs.h>
#include <machine/ieeefp.h>

#endif /* !_FLOATINGPOINT_H_ */


code:
/*-
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * William Jolitz.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)npx.h	5.3 (Berkeley) 1/18/91
 * $FreeBSD: release/9.0.0/sys/amd64/include/fpu.h 215865 2010-11-26 14:50:42Z kib $
 */

/*
 * Floating Point Data Structures and Constants
 * W. Jolitz 1/90
 */

#ifndef _MACHINE_FPU_H_
#define	_MACHINE_FPU_H_

/* Contents of each x87 floating point accumulator */
struct fpacc87 {
	u_char	fp_bytes[10];
};

/* Contents of each SSE extended accumulator */
struct  xmmacc {
	u_char	xmm_bytes[16];
};

struct  envxmm {
	u_int16_t	en_cw;		/* control word (16bits) */
	u_int16_t	en_sw;		/* status word (16bits) */
	u_int8_t	en_tw;		/* tag word (8bits) */
	u_int8_t	en_zero;
	u_int16_t	en_opcode;	/* opcode last executed (11 bits ) */
	u_int64_t	en_rip;		/* floating point instruction pointer */
	u_int64_t	en_rdp;		/* floating operand pointer */
	u_int32_t	en_mxcsr;	/* SSE sontorol/status register */
	u_int32_t	en_mxcsr_mask;	/* valid bits in mxcsr */
};

struct  savefpu {
	struct	envxmm	sv_env;
	struct {
		struct fpacc87	fp_acc;
		u_char		fp_pad[6];      /* padding */
	} sv_fp[8];
	struct xmmacc	sv_xmm[16];
	u_char sv_pad[96];
} __aligned(16);

#ifdef _KERNEL
struct fpu_kern_ctx {
	struct savefpu hwstate;
	struct savefpu *prev;
	uint32_t flags;
};
#define	FPU_KERN_CTX_FPUINITDONE 0x01

#define	PCB_USER_FPU(pcb) (((pcb)->pcb_flags & PCB_KERNFPU) == 0)
#endif

/*
 * The hardware default control word for i387's and later coprocessors is
 * 0x37F, giving:
 *
 *	round to nearest
 *	64-bit precision
 *	all exceptions masked.
 *
 * FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc
 * because of the difference between memory and fpu register stack arguments.
 * If its using an intermediate fpu register, it has 80/64 bits to work
 * with.  If it uses memory, it has 64/53 bits to work with.  However,
 * gcc is aware of this and goes to a fair bit of trouble to make the
 * best use of it.
 *
 * This is mostly academic for AMD64, because the ABI prefers the use
 * SSE2 based math.  For FreeBSD/amd64, we go with the default settings.
 */
#define	__INITIAL_FPUCW__	0x037F
#define	__INITIAL_FPUCW_I386__	0x127F
#define	__INITIAL_MXCSR__	0x1F80
#define	__INITIAL_MXCSR_MASK__	0xFFBF

#ifdef _KERNEL
void	fpudna(void);
void	fpudrop(void);
void	fpuexit(struct thread *td);
int	fpuformat(void);
int	fpugetregs(struct thread *td);
void	fpuinit(void);
void	fpusetregs(struct thread *td, struct savefpu *addr);
int	fputrap(void);
void	fpuuserinited(struct thread *td);
int	fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx,
	    u_int flags);
int	fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx);
int	fpu_kern_thread(u_int flags);
int	is_fpu_kern_thread(u_int flags);

/*
 * Flags for fpu_kern_enter() and fpu_kern_thread().
 */
#define	FPU_KERN_NORMAL	0x0000

#endif

#endif /* !_MACHINE_FPU_H_ */


code:
/*-
 * Copyright (c) 2003 Peter Wemm.
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * William Jolitz.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)frame.h	5.2 (Berkeley) 1/18/91
 * $FreeBSD: release/9.0.0/sys/amd64/include/frame.h 190620 2009-04-01 13:09:26Z kib $
 */

#ifndef _MACHINE_FRAME_H_
#define _MACHINE_FRAME_H_ 1

/*
 * System stack frames.
 */

/*
 * Exception/Trap Stack Frame
 *
 * The ordering of this is specifically so that we can take first 6
 * the syscall arguments directly from the beginning of the frame.
 */

#ifndef MIRA_PLATFORM
struct trapframe {
	register_t	tf_rdi;
	register_t	tf_rsi;
	register_t	tf_rdx;
	register_t	tf_rcx;
	register_t	tf_r8;
	register_t	tf_r9;
	register_t	tf_rax;
	register_t	tf_rbx;
	register_t	tf_rbp;
	register_t	tf_r10;
	register_t	tf_r11;
	register_t	tf_r12;
	register_t	tf_r13;
	register_t	tf_r14;
	register_t	tf_r15;
	uint32_t	tf_trapno;
	uint16_t	tf_fs;
	uint16_t	tf_gs;
	register_t	tf_addr;
	uint32_t	tf_flags;
	uint16_t	tf_es;
	uint16_t	tf_ds;
	/* below portion defined in hardware */
	register_t	tf_err;
	register_t	tf_rip;
	register_t	tf_cs;
	register_t	tf_rflags;
	register_t	tf_rsp;
	register_t	tf_ss;
};
#else
struct trapframe
{
	register_t tf_rdi;			// 0x00
	register_t tf_rsi;			// 0x08
	register_t tf_rdx;			// 0x10
	register_t tf_rcx;			// 0x18
	register_t tf_r8;			// 0x20
	register_t tf_r9;			// 0x28
	register_t tf_rax;			// 0x30
	register_t tf_rbx;			// 0x38
	register_t tf_rbp;			// 0x40
	register_t tf_r10;			// 0x48
	register_t tf_r11;			// 0x50
	register_t tf_r12;			// 0x58
	register_t tf_r13;			// 0x60
	register_t tf_r14;			// 0x68
	register_t tf_r15;			// 0x70
	uint32_t tf_trapno;			// 0x78
	uint16_t tf_fs;				// 0x7C
	uint16_t tf_gs;				// 0x7E
	register_t tf_addr;			// 0x80
	uint32_t tf_flags;			// 0x88
	uint16_t tf_es;				// 0x8C
	uint16_t tf_ds;				// 0x8E

	register_t tf_last_branch_from;		// 0x90
	register_t tf_last_branch_to;		// 0x98

	/* below portion defined in hardware */
	register_t tf_err;			// 0xA0
	register_t tf_rip;			// 0xA8
	register_t tf_cs;			// 0xB0
	register_t tf_rflags;			// 0xB8
	register_t tf_rsp;			// 0xC0
	register_t tf_ss;			// 0xC8
};
#endif

#define	TF_HASSEGS	0x1
/* #define	_MC_HASBASES	0x2 */

#endif /* _MACHINE_FRAME_H_ */


code:
/*-
 * Copyright (c) 2004 Marcel Moolenaar
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/amd64/include/gdb_machdep.h 166520 2007-02-05 21:48:32Z jhb $
 */

#ifndef _MACHINE_GDB_MACHDEP_H_
#define	_MACHINE_GDB_MACHDEP_H_

#define	GDB_BUFSZ	(GDB_NREGS * 16)
#define	GDB_NREGS	56
#define	GDB_REG_PC	16

static __inline size_t
gdb_cpu_regsz(int regnum)
{
	return ((regnum > 16 && regnum < 24) ? 4 : 8);
}

static __inline int
gdb_cpu_query(void)
{
	return (0);
}

void *gdb_cpu_getreg(int, size_t *);
void gdb_cpu_setreg(int, void *);
int gdb_cpu_signal(int, int);

#endif /* !_MACHINE_GDB_MACHDEP_H_ */


code:
/*-
 * Copyright (c) 2003 Peter Wemm.
 * Copyright (c) 1990 Andrew Moore, Talke Studio
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * 	from: @(#) ieeefp.h 	1.0 (Berkeley) 9/23/93
 * $FreeBSD: release/9.0.0/sys/amd64/include/ieeefp.h 175231 2008-01-11 17:11:32Z bde $
 */

#ifndef _MACHINE_IEEEFP_H_
#define _MACHINE_IEEEFP_H_

/*
 * IEEE floating point type, constant and function definitions.
 * XXX: {FP,SSE}*FLD and {FP,SSE}*OFF are undocumented pollution.
 */

#ifndef _SYS_CDEFS_H_
#error this file needs sys/cdefs.h as a prerequisite
#endif

/*
 * Rounding modes.
 */
typedef enum {
	FP_RN=0,	/* round to nearest */
	FP_RM,		/* round down towards minus infinity */
	FP_RP,		/* round up towards plus infinity */
	FP_RZ		/* truncate */
} fp_rnd_t;

/*
 * Precision (i.e., rounding precision) modes.
 */
typedef enum {
	FP_PS=0,	/* 24 bit (single-precision) */
	FP_PRS,		/* reserved */
	FP_PD,		/* 53 bit (double-precision) */
	FP_PE		/* 64 bit (extended-precision) */
} fp_prec_t;

#define fp_except_t	int

/*
 * Exception bit masks.
 */
#define FP_X_INV	0x01	/* invalid operation */
#define FP_X_DNML	0x02	/* denormal */
#define FP_X_DZ		0x04	/* zero divide */
#define FP_X_OFL	0x08	/* overflow */
#define FP_X_UFL	0x10	/* underflow */
#define FP_X_IMP	0x20	/* (im)precision */
#define FP_X_STK	0x40	/* stack fault */

/*
 * FPU control word bit-field masks.
 */
#define FP_MSKS_FLD	0x3f	/* exception masks field */
#define FP_PRC_FLD	0x300	/* precision control field */
#define	FP_RND_FLD	0xc00	/* rounding control field */

/*
 * FPU status word bit-field masks.
 */
#define FP_STKY_FLD	0x3f	/* sticky flags field */

/*
 * SSE mxcsr register bit-field masks.
 */
#define	SSE_STKY_FLD	0x3f	/* exception flags */
#define	SSE_DAZ_FLD	0x40	/* Denormals are zero */
#define	SSE_MSKS_FLD	0x1f80	/* exception masks field */
#define	SSE_RND_FLD	0x6000	/* rounding control */
#define	SSE_FZ_FLD	0x8000	/* flush to zero on underflow */

/*
 * FPU control word bit-field offsets (shift counts).
 */
#define FP_MSKS_OFF	0	/* exception masks offset */
#define FP_PRC_OFF	8	/* precision control offset */
#define	FP_RND_OFF	10	/* rounding control offset */

/*
 * FPU status word bit-field offsets (shift counts).
 */
#define FP_STKY_OFF	0	/* sticky flags offset */

/*
 * SSE mxcsr register bit-field offsets (shift counts).
 */
#define	SSE_STKY_OFF	0	/* exception flags offset */
#define	SSE_DAZ_OFF	6	/* DAZ exception mask offset */
#define	SSE_MSKS_OFF	7	/* other exception masks offset */
#define	SSE_RND_OFF	13	/* rounding control offset */
#define	SSE_FZ_OFF	15	/* flush to zero offset */

#ifdef __GNUCLIKE_ASM

#define	__fldcw(addr)	__asm __volatile("fldcw %0" : : "m" (*(addr)))
#define	__fldenv(addr)	__asm __volatile("fldenv %0" : : "m" (*(addr)))
#define	__fnstcw(addr)	__asm __volatile("fnstcw %0" : "=m" (*(addr)))
#define	__fnstenv(addr)	__asm __volatile("fnstenv %0" : "=m" (*(addr)))
#define	__fnstsw(addr)	__asm __volatile("fnstsw %0" : "=m" (*(addr)))
#define	__ldmxcsr(addr)	__asm __volatile("ldmxcsr %0" : : "m" (*(addr)))
#define	__stmxcsr(addr)	__asm __volatile("stmxcsr %0" : "=m" (*(addr)))

/*
 * Load the control word.  Be careful not to trap if there is a currently
 * unmasked exception (ones that will become freshly unmasked are not a
 * problem).  This case must be handled by a save/restore of the
 * environment or even of the full x87 state.  Accessing the environment
 * is very inefficient, so only do it when necessary.
 */
static __inline void
__fnldcw(unsigned short _cw, unsigned short _newcw)
{
	struct {
		unsigned _cw;
		unsigned _other[6];
	} _env;
	unsigned short _sw;

	if ((_cw & FP_MSKS_FLD) != FP_MSKS_FLD) {
		__fnstsw(&_sw);
		if (((_sw & ~_cw) & FP_STKY_FLD) != 0) {
			__fnstenv(&_env);
			_env._cw = _newcw;
			__fldenv(&_env);
			return;
		}
	}
	__fldcw(&_newcw);
}

/*
 * General notes about conflicting SSE vs FP status bits.
 * This code assumes that software will not fiddle with the control
 * bits of the SSE and x87 in such a way to get them out of sync and
 * still expect this to work.  Break this at your peril.
 * Because I based this on the i386 port, the x87 state is used for
 * the fpget*() functions, and is shadowed into the SSE state for
 * the fpset*() functions.  For dual source fpget*() functions, I
 * merge the two together.  I think.
 */

static __inline fp_rnd_t
__fpgetround(void)
{
	unsigned short _cw;

	__fnstcw(&_cw);
	return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF));
}

static __inline fp_rnd_t
__fpsetround(fp_rnd_t _m)
{
	fp_rnd_t _p;
	unsigned _mxcsr;
	unsigned short _cw, _newcw;

	__fnstcw(&_cw);
	_p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF);
	_newcw = _cw & ~FP_RND_FLD;
	_newcw |= (_m << FP_RND_OFF) & FP_RND_FLD;
	__fnldcw(_cw, _newcw);
	__stmxcsr(&_mxcsr);
	_mxcsr &= ~SSE_RND_FLD;
	_mxcsr |= (_m << SSE_RND_OFF) & SSE_RND_FLD;
	__ldmxcsr(&_mxcsr);
	return (_p);
}

/*
 * Get or set the rounding precision for x87 arithmetic operations.
 * There is no equivalent SSE mode or control.
 */

static __inline fp_prec_t
__fpgetprec(void)
{
	unsigned short _cw;

	__fnstcw(&_cw);
	return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF));
}

static __inline fp_prec_t
__fpsetprec(fp_prec_t _m)
{
	fp_prec_t _p;
	unsigned short _cw, _newcw;

	__fnstcw(&_cw);
	_p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF);
	_newcw = _cw & ~FP_PRC_FLD;
	_newcw |= (_m << FP_PRC_OFF) & FP_PRC_FLD;
	__fnldcw(_cw, _newcw);
	return (_p);
}

/*
 * Get or set the exception mask.
 * Note that the x87 mask bits are inverted by the API -- a mask bit of 1
 * means disable for x87 and SSE, but for fp*mask() it means enable.
 */

static __inline fp_except_t
__fpgetmask(void)
{
	unsigned short _cw;

	__fnstcw(&_cw);
	return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF);
}

static __inline fp_except_t
__fpsetmask(fp_except_t _m)
{
	fp_except_t _p;
	unsigned _mxcsr;
	unsigned short _cw, _newcw;

	__fnstcw(&_cw);
	_p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF;
	_newcw = _cw & ~FP_MSKS_FLD;
	_newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD;
	__fnldcw(_cw, _newcw);
	__stmxcsr(&_mxcsr);
	/* XXX should we clear non-ieee SSE_DAZ_FLD and SSE_FZ_FLD ? */
	_mxcsr &= ~SSE_MSKS_FLD;
	_mxcsr |= (~_m << SSE_MSKS_OFF) & SSE_MSKS_FLD;
	__ldmxcsr(&_mxcsr);
	return (_p);
}

static __inline fp_except_t
__fpgetsticky(void)
{
	unsigned _ex, _mxcsr;
	unsigned short _sw;

	__fnstsw(&_sw);
	_ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF;
	__stmxcsr(&_mxcsr);
	_ex |= (_mxcsr & SSE_STKY_FLD) >> SSE_STKY_OFF;
	return ((fp_except_t)_ex);
}

#endif /* __GNUCLIKE_ASM */

#if !defined(__IEEEFP_NOINLINES__) && defined(__GNUCLIKE_ASM)

#define	fpgetmask()	__fpgetmask()
#define	fpgetprec()	__fpgetprec()
#define	fpgetround()	__fpgetround()
#define	fpgetsticky()	__fpgetsticky()
#define	fpsetmask(m)	__fpsetmask(m)
#define	fpsetprec(m)	__fpsetprec(m)
#define	fpsetround(m)	__fpsetround(m)

/* Suppress prototypes in the MI header. */
#define	_IEEEFP_INLINED_	1

#else /* !(!__IEEEFP_NOINLINES__ && __GNUCLIKE_ASM) */

/* Augment the userland declarations. */
__BEGIN_DECLS
fp_prec_t	fpgetprec(void);
fp_prec_t	fpsetprec(fp_prec_t);
__END_DECLS

#endif /* !__IEEEFP_NOINLINES__ && __GNUCLIKE_ASM */

#endif /* !_MACHINE_IEEEFP_H_ */