1 /*
2 Copyright (C) 2007 Remon Sijrier
3
4 Copyright (C) 2000-2007 Paul Davis
5
6 This file is part of Traverso
7
8 Traverso is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21
22 */
23
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <stdio.h>
27
28 #include <fpu.h>
29
FPU()30 FPU::FPU ()
31 {
32 unsigned long cpuflags = 0;
33
34 _flags = Flags (0);
35
36 #ifdef ARCH_X86
37
38 #ifndef USE_X86_64_ASM
39 asm volatile (
40 "mov $1, %%eax\n"
41 "pushl %%ebx\n"
42 "cpuid\n"
43 "movl %%edx, %0\n"
44 "popl %%ebx\n"
45 : "=r" (cpuflags)
46 :
47 : "%eax", "%ecx", "%edx", "memory"
48 );
49
50 #else
51
52 asm volatile (
53 "pushq %%rbx\n"
54 "movq $1, %%rax\n"
55 "cpuid\n"
56 "movq %%rdx, %0\n"
57 "popq %%rbx\n"
58 : "=r" (cpuflags)
59 :
60 : "%rax", "%rcx", "%rdx", "memory"
61 );
62
63 #endif /* USE_X86_64_ASM */
64
65 if (cpuflags & (1<<25)) {
66 _flags = Flags (_flags | (HasSSE|HasFlushToZero));
67 }
68
69 if (cpuflags & (1<<26)) {
70 _flags = Flags (_flags | HasSSE2);
71 }
72
73 if (cpuflags & (1 << 24)) {
74
75 char* fxbuf = 0;
76 char** temp = &fxbuf;
77
78 #ifdef NO_POSIX_MEMALIGN
79 if ((fxbuf = (char *) malloc(512)) == 0)
80 #else
81 if (posix_memalign ((void**)temp, 16, 512))
82 #endif
83 {
84 printf("FPU() ERROR: cannot allocate 16 byte aligned buffer for h/w feature detection");
85 } else {
86
87 asm volatile (
88 "fxsave (%0)"
89 :
90 : "r" (fxbuf)
91 : "memory"
92 );
93
94 uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]);
95
96 /* if the mask is zero, set its default value (from intel specs) */
97
98 if (mxcsr_mask == 0) {
99 mxcsr_mask = 0xffbf;
100 }
101
102 if (mxcsr_mask & (1<<6)) {
103 _flags = Flags (_flags | HasDenormalsAreZero);
104 }
105
106 free (fxbuf);
107 }
108 }
109 #endif
110 }
111
~FPU()112 FPU::~FPU ()
113 {
114 }
115