xref: /freebsd-src/sys/x86/include/fpu.h (revision b9951017bab396e24042e85632e2cc34ee0329ff)
178664507STijl Coosemans /*-
278664507STijl Coosemans  * Copyright (c) 1990 The Regents of the University of California.
378664507STijl Coosemans  * All rights reserved.
478664507STijl Coosemans  *
578664507STijl Coosemans  * This code is derived from software contributed to Berkeley by
678664507STijl Coosemans  * William Jolitz.
778664507STijl Coosemans  *
878664507STijl Coosemans  * Redistribution and use in source and binary forms, with or without
978664507STijl Coosemans  * modification, are permitted provided that the following conditions
1078664507STijl Coosemans  * are met:
1178664507STijl Coosemans  * 1. Redistributions of source code must retain the above copyright
1278664507STijl Coosemans  *    notice, this list of conditions and the following disclaimer.
1378664507STijl Coosemans  * 2. Redistributions in binary form must reproduce the above copyright
1478664507STijl Coosemans  *    notice, this list of conditions and the following disclaimer in the
1578664507STijl Coosemans  *    documentation and/or other materials provided with the distribution.
16fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
1778664507STijl Coosemans  *    may be used to endorse or promote products derived from this software
1878664507STijl Coosemans  *    without specific prior written permission.
1978664507STijl Coosemans  *
2078664507STijl Coosemans  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2178664507STijl Coosemans  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2278664507STijl Coosemans  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2378664507STijl Coosemans  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2478664507STijl Coosemans  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2578664507STijl Coosemans  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2678664507STijl Coosemans  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2778664507STijl Coosemans  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2878664507STijl Coosemans  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2978664507STijl Coosemans  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3078664507STijl Coosemans  * SUCH DAMAGE.
3178664507STijl Coosemans  */
3278664507STijl Coosemans 
3378664507STijl Coosemans /*
3478664507STijl Coosemans  * Floating Point Data Structures and Constants
3578664507STijl Coosemans  * W. Jolitz 1/90
3678664507STijl Coosemans  */
3778664507STijl Coosemans 
3878664507STijl Coosemans #ifndef _X86_FPU_H_
3978664507STijl Coosemans #define	_X86_FPU_H_
4078664507STijl Coosemans 
4178664507STijl Coosemans /* Environment information of floating point unit. */
4278664507STijl Coosemans struct env87 {
4378664507STijl Coosemans 	int32_t		en_cw;		/* control word (16bits) */
4478664507STijl Coosemans 	int32_t		en_sw;		/* status word (16bits) */
4578664507STijl Coosemans 	int32_t		en_tw;		/* tag word (16bits) */
4678664507STijl Coosemans 	int32_t		en_fip;		/* fp instruction pointer */
4778664507STijl Coosemans 	uint16_t	en_fcs;		/* fp code segment selector */
4878664507STijl Coosemans 	uint16_t	en_opcode;	/* opcode last executed (11 bits) */
4978664507STijl Coosemans 	int32_t		en_foo;		/* fp operand offset */
5078664507STijl Coosemans 	int32_t		en_fos;		/* fp operand segment selector */
5178664507STijl Coosemans };
5278664507STijl Coosemans 
5378664507STijl Coosemans /* Contents of each x87 floating point accumulator. */
5478664507STijl Coosemans struct fpacc87 {
5578664507STijl Coosemans 	uint8_t		fp_bytes[10];
5678664507STijl Coosemans };
5778664507STijl Coosemans 
5878664507STijl Coosemans /* Floating point context. (i386 fnsave/frstor) */
5978664507STijl Coosemans struct save87 {
6078664507STijl Coosemans 	struct env87	sv_env;		/* floating point control/status */
6178664507STijl Coosemans 	struct fpacc87	sv_ac[8];	/* accumulator contents, 0-7 */
6278664507STijl Coosemans 	uint8_t		sv_pad0[4];	/* saved status word (now unused) */
63180e57e5SJohn Baldwin 	uint8_t		sv_pad[64];
6478664507STijl Coosemans };
6578664507STijl Coosemans 
6678664507STijl Coosemans /* Contents of each SSE extended accumulator. */
6778664507STijl Coosemans struct xmmacc {
6878664507STijl Coosemans 	uint8_t		xmm_bytes[16];
6978664507STijl Coosemans };
7078664507STijl Coosemans 
7178664507STijl Coosemans /* Contents of the upper 16 bytes of each AVX extended accumulator. */
7278664507STijl Coosemans struct ymmacc {
7378664507STijl Coosemans 	uint8_t		ymm_bytes[16];
7478664507STijl Coosemans };
7578664507STijl Coosemans 
7678664507STijl Coosemans /* Rename structs below depending on machine architecture. */
7778664507STijl Coosemans #ifdef __i386__
7878664507STijl Coosemans #define	__envxmm32	envxmm
7978664507STijl Coosemans #else
8078664507STijl Coosemans #define	__envxmm32	envxmm32
8178664507STijl Coosemans #define	__envxmm64	envxmm
8278664507STijl Coosemans #endif
8378664507STijl Coosemans 
8478664507STijl Coosemans struct __envxmm32 {
8578664507STijl Coosemans 	uint16_t	en_cw;		/* control word (16bits) */
8678664507STijl Coosemans 	uint16_t	en_sw;		/* status word (16bits) */
8778664507STijl Coosemans 	uint16_t	en_tw;		/* tag word (16bits) */
8878664507STijl Coosemans 	uint16_t	en_opcode;	/* opcode last executed (11 bits) */
8978664507STijl Coosemans 	uint32_t	en_fip;		/* fp instruction pointer */
9078664507STijl Coosemans 	uint16_t	en_fcs;		/* fp code segment selector */
9178664507STijl Coosemans 	uint16_t	en_pad0;	/* padding */
9278664507STijl Coosemans 	uint32_t	en_foo;		/* fp operand offset */
9378664507STijl Coosemans 	uint16_t	en_fos;		/* fp operand segment selector */
9478664507STijl Coosemans 	uint16_t	en_pad1;	/* padding */
9578664507STijl Coosemans 	uint32_t	en_mxcsr;	/* SSE control/status register */
9678664507STijl Coosemans 	uint32_t	en_mxcsr_mask;	/* valid bits in mxcsr */
9778664507STijl Coosemans };
9878664507STijl Coosemans 
9978664507STijl Coosemans struct __envxmm64 {
10078664507STijl Coosemans 	uint16_t	en_cw;		/* control word (16bits) */
10178664507STijl Coosemans 	uint16_t	en_sw;		/* status word (16bits) */
10278664507STijl Coosemans 	uint8_t		en_tw;		/* tag word (8bits) */
10378664507STijl Coosemans 	uint8_t		en_zero;
10478664507STijl Coosemans 	uint16_t	en_opcode;	/* opcode last executed (11 bits ) */
10578664507STijl Coosemans 	uint64_t	en_rip;		/* fp instruction pointer */
10678664507STijl Coosemans 	uint64_t	en_rdp;		/* fp operand pointer */
10778664507STijl Coosemans 	uint32_t	en_mxcsr;	/* SSE control/status register */
10878664507STijl Coosemans 	uint32_t	en_mxcsr_mask;	/* valid bits in mxcsr */
10978664507STijl Coosemans };
11078664507STijl Coosemans 
11178664507STijl Coosemans /* Floating point context. (i386 fxsave/fxrstor) */
11278664507STijl Coosemans struct savexmm {
11378664507STijl Coosemans 	struct __envxmm32	sv_env;
11478664507STijl Coosemans 	struct {
11578664507STijl Coosemans 		struct fpacc87	fp_acc;
11678664507STijl Coosemans 		uint8_t		fp_pad[6];      /* padding */
11778664507STijl Coosemans 	} sv_fp[8];
11878664507STijl Coosemans 	struct xmmacc		sv_xmm[8];
11978664507STijl Coosemans 	uint8_t			sv_pad[224];
12078664507STijl Coosemans } __aligned(16);
12178664507STijl Coosemans 
12278664507STijl Coosemans #ifdef __i386__
12378664507STijl Coosemans union savefpu {
12478664507STijl Coosemans 	struct save87	sv_87;
12578664507STijl Coosemans 	struct savexmm	sv_xmm;
12678664507STijl Coosemans };
12778664507STijl Coosemans #else
12878664507STijl Coosemans /* Floating point context. (amd64 fxsave/fxrstor) */
12978664507STijl Coosemans struct savefpu {
13078664507STijl Coosemans 	struct __envxmm64	sv_env;
13178664507STijl Coosemans 	struct {
13278664507STijl Coosemans 		struct fpacc87	fp_acc;
13378664507STijl Coosemans 		uint8_t		fp_pad[6];	/* padding */
13478664507STijl Coosemans 	} sv_fp[8];
13578664507STijl Coosemans 	struct xmmacc		sv_xmm[16];
13678664507STijl Coosemans 	uint8_t			sv_pad[96];
13778664507STijl Coosemans } __aligned(16);
13878664507STijl Coosemans #endif
13978664507STijl Coosemans 
14078664507STijl Coosemans struct xstate_hdr {
14178664507STijl Coosemans 	uint64_t	xstate_bv;
142f3f50976SKonstantin Belousov 	uint64_t	xstate_xcomp_bv;
143f3f50976SKonstantin Belousov 	uint8_t		xstate_rsrv0[8];
14478664507STijl Coosemans 	uint8_t		xstate_rsrv[40];
14578664507STijl Coosemans };
146f3f50976SKonstantin Belousov #define	XSTATE_XCOMP_BV_COMPACT	(1ULL << 63)
14778664507STijl Coosemans 
14878664507STijl Coosemans struct savexmm_xstate {
14978664507STijl Coosemans 	struct xstate_hdr	sx_hd;
15078664507STijl Coosemans 	struct ymmacc		sx_ymm[16];
15178664507STijl Coosemans };
15278664507STijl Coosemans 
15378664507STijl Coosemans struct savexmm_ymm {
15478664507STijl Coosemans 	struct __envxmm32	sv_env;
15578664507STijl Coosemans 	struct {
15678664507STijl Coosemans 		struct fpacc87	fp_acc;
15778664507STijl Coosemans 		int8_t		fp_pad[6];	/* padding */
15878664507STijl Coosemans 	} sv_fp[8];
15978664507STijl Coosemans 	struct xmmacc		sv_xmm[16];
16078664507STijl Coosemans 	uint8_t			sv_pad[96];
16178664507STijl Coosemans 	struct savexmm_xstate	sv_xstate;
16278664507STijl Coosemans } __aligned(64);
16378664507STijl Coosemans 
16478664507STijl Coosemans struct savefpu_xstate {
16578664507STijl Coosemans 	struct xstate_hdr	sx_hd;
16678664507STijl Coosemans 	struct ymmacc		sx_ymm[16];
16778664507STijl Coosemans };
16878664507STijl Coosemans 
16978664507STijl Coosemans struct savefpu_ymm {
17078664507STijl Coosemans 	struct __envxmm64	sv_env;
17178664507STijl Coosemans 	struct {
17278664507STijl Coosemans 		struct fpacc87	fp_acc;
17378664507STijl Coosemans 		int8_t		fp_pad[6];	/* padding */
17478664507STijl Coosemans 	} sv_fp[8];
17578664507STijl Coosemans 	struct xmmacc		sv_xmm[16];
17678664507STijl Coosemans 	uint8_t			sv_pad[96];
17778664507STijl Coosemans 	struct savefpu_xstate	sv_xstate;
17878664507STijl Coosemans } __aligned(64);
17978664507STijl Coosemans 
18078664507STijl Coosemans #undef __envxmm32
18178664507STijl Coosemans #undef __envxmm64
18278664507STijl Coosemans 
18378664507STijl Coosemans /*
18478664507STijl Coosemans  * The hardware default control word for i387's and later coprocessors is
18578664507STijl Coosemans  * 0x37F, giving:
18678664507STijl Coosemans  *
18778664507STijl Coosemans  *	round to nearest
18878664507STijl Coosemans  *	64-bit precision
18978664507STijl Coosemans  *	all exceptions masked.
19078664507STijl Coosemans  *
19178664507STijl Coosemans  * FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc
19278664507STijl Coosemans  * because of the difference between memory and fpu register stack arguments.
19378664507STijl Coosemans  * If its using an intermediate fpu register, it has 80/64 bits to work
19478664507STijl Coosemans  * with.  If it uses memory, it has 64/53 bits to work with.  However,
19578664507STijl Coosemans  * gcc is aware of this and goes to a fair bit of trouble to make the
19678664507STijl Coosemans  * best use of it.
19778664507STijl Coosemans  *
19878664507STijl Coosemans  * This is mostly academic for AMD64, because the ABI prefers the use
19978664507STijl Coosemans  * SSE2 based math.  For FreeBSD/amd64, we go with the default settings.
20078664507STijl Coosemans  */
20178664507STijl Coosemans #define	__INITIAL_FPUCW__	0x037F
20278664507STijl Coosemans #define	__INITIAL_FPUCW_I386__	0x127F
20378664507STijl Coosemans #define	__INITIAL_NPXCW__	__INITIAL_FPUCW_I386__
20478664507STijl Coosemans #define	__INITIAL_MXCSR__	0x1F80
20578664507STijl Coosemans #define	__INITIAL_MXCSR_MASK__	0xFFBF
20678664507STijl Coosemans 
207180e57e5SJohn Baldwin /*
208180e57e5SJohn Baldwin  * The current value of %xcr0 is saved in the sv_pad[] field of the FPU
209180e57e5SJohn Baldwin  * state in the NT_X86_XSTATE note in core dumps.  This offset is chosen
210180e57e5SJohn Baldwin  * to match the offset used by NT_X86_XSTATE in other systems.
211180e57e5SJohn Baldwin  */
212180e57e5SJohn Baldwin #define	X86_XSTATE_XCR0_OFFSET	464
213180e57e5SJohn Baldwin 
214cc1cb9eaSJohn Baldwin #ifdef _KERNEL
215cc1cb9eaSJohn Baldwin /*
216cc1cb9eaSJohn Baldwin  * CR0_MP and CR0_EM are always set.  Use CR0_TS to force traps when
217cc1cb9eaSJohn Baldwin  * FPU access is disabled.
218cc1cb9eaSJohn Baldwin  */
219cc1cb9eaSJohn Baldwin #define	fpu_enable()	clts()
220cc1cb9eaSJohn Baldwin #define	fpu_disable()	load_cr0(rcr0() | CR0_TS)
2217bcaff05SBojan Novković 
2227bcaff05SBojan Novković bool	xsave_extfeature_supported(uint64_t feature, bool supervisor);
2237bcaff05SBojan Novković bool	xsave_extension_supported(uint64_t extension);
2247bcaff05SBojan Novković size_t	xsave_area_hdr_offset(void);
225*b9951017SBojan Novković size_t	xsave_area_offset(uint64_t xstate_bv, uint64_t feature, bool compact,
226*b9951017SBojan Novković     bool supervisor);
227*b9951017SBojan Novković size_t	xsave_area_size(uint64_t xstate_bv, bool compact, bool supervisor);
228cc1cb9eaSJohn Baldwin #endif
229cc1cb9eaSJohn Baldwin 
23078664507STijl Coosemans #endif /* !_X86_FPU_H_ */
231