3 * Shared between UX and native IA32.
6 INTERFACE[ia32,amd64,ux]:
12 struct fpu_regs // saved FPU registers
21 long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
36 Unsigned32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
37 Unsigned32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
38 Unsigned32 padding[24];
54 enum Variants _variant;
56 static unsigned _state_size;
57 static unsigned _state_align;
60 IMPLEMENTATION[ia32,amd64,ux]:
64 #include "fpu_state.h"
67 #include "static_assert.h"
69 unsigned Fpu::_state_size;
70 unsigned Fpu::_state_align;
73 * Initialize FPU or SSE state
74 * We don't use finit, because it is slow. Initializing the context in
75 * memory and fetching it via restore_state is supposedly faster
77 IMPLEMENT inline NEEDS ["cpu.h", "fpu_state.h", "globals.h", "regdefs.h",
78 "static_assert.h", <cstring>]
80 Fpu::init_state(Fpu_state *s)
82 Cpu const &_cpu = Cpu::cpus.cpu(current_cpu());
83 if (_cpu.features() & FEAT_FXSR)
85 assert (_state_size >= sizeof (sse_regs));
86 sse_regs *sse = reinterpret_cast<sse_regs *>(s->state_buffer());
88 memset(sse, 0, sizeof (*sse));
91 if (_cpu.features() & FEAT_SSE)
94 if (_cpu.ext_features() & FEATX_XSAVE)
95 memset(reinterpret_cast<Xsave_buffer *>(s->state_buffer())->header, 0,
96 sizeof (Xsave_buffer::header));
98 static_assert(sizeof (sse_regs) == 512, "SSE-regs size not 512 bytes");
102 fpu_regs *fpu = reinterpret_cast<fpu_regs *>(s->state_buffer());
104 assert (_state_size >= sizeof (*fpu));
105 memset(fpu, 0, sizeof (*fpu));
106 fpu->cwd = 0xffff037f;
107 fpu->swd = 0xffff0000;
108 fpu->twd = 0xffffffff;
109 fpu->fos = 0xffff0000;
115 Fpu::init(unsigned cpu)
117 // Mark FPU busy, so that first FPU operation will yield an exception
120 // At first, noone owns the FPU
125 printf("FPU%d: %s%s\n", cpu,
126 Cpu::cpus.cpu(cpu).features() & FEAT_SSE ? "SSE " : "",
127 Cpu::cpus.cpu(cpu).ext_features() & FEATX_AVX ? "AVX " : "");
129 unsigned cpu_align = 0, cpu_size = 0;
131 if (Cpu::cpus.cpu(cpu).ext_features() & FEATX_XSAVE)
135 Cpu::cpus.cpu(cpu).update_features_info();
137 Unsigned32 eax, ecx, edx;
138 Cpu::cpus.cpu(cpu).cpuid_0xd(0, &eax, &cpu_size, &ecx, &edx);
140 fpu(cpu)._variant = Variant_xsave;
142 else if (Cpu::have_fxsr())
144 cpu_size = sizeof(sse_regs);
146 fpu(cpu)._variant = Variant_fxsr;
150 cpu_size = sizeof(fpu_regs);
152 fpu(cpu)._variant = Variant_fpu;
155 if (cpu_size > _state_size)
156 _state_size = cpu_size;
157 if (cpu_align > _state_align)
158 _state_align = cpu_align;
163 * Return size of FPU context structure, depending on i387 or SSE
164 * @return size of FPU context structure
166 IMPLEMENT inline NEEDS ["cpu.h", "regdefs.h"]
174 * Return recommended FPU context alignment, depending on i387 or SSE
175 * @return recommended FPU context alignment
177 IMPLEMENT inline NEEDS ["cpu.h", "regdefs.h"]