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