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