X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Ffpu.cc;h=5d81cd2fd35e52407c9177b50bacceb621a565b7;hb=57f9a4c344fc1142530d66283f07e9aa6524461c;hp=1018414d9b72a3ab68c9c4b92608fa116833ef5a;hpb=639bb7dc5d61054615fee8e4da272ad5ce9140ee;p=ardour.git diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc index 1018414d9b..5d81cd2fd3 100644 --- a/libs/pbd/fpu.cc +++ b/libs/pbd/fpu.cc @@ -1,9 +1,29 @@ +/* + Copyright (C) 2012 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef COMPILER_MSVC #include "libpbd-config.h" #define _XOPEN_SOURCE 600 #include // for memset #include #include +#include #include "pbd/fpu.h" #include "pbd/error.h" @@ -67,40 +87,53 @@ FPU::FPU () if (cpuflags & (1 << 24)) { - char* fxbuf = 0; + char** fxbuf = 0; -#ifdef NO_POSIX_MEMALIGN - if ((fxbuf = (char *) malloc(512)) == 0) + /* DAZ wasn't available in the first version of SSE. Since + setting a reserved bit in MXCSR causes a general protection + fault, we need to be able to check the availability of this + feature without causing problems. To do this, one needs to + set up a 512-byte area of memory to save the SSE state to, + using fxsave, and then one needs to inspect bytes 28 through + 31 for the MXCSR_MASK value. If bit 6 is set, DAZ is + supported, otherwise, it isn't. + */ + +#ifndef HAVE_POSIX_MEMALIGN + fxbuf = (char **) malloc (sizeof (char *)); + assert (fxbuf); + *fxbuf = (char *) malloc (512); + assert (*fxbuf); #else - if (posix_memalign ((void**)&fxbuf, 16, 512)) + posix_memalign ((void **) &fxbuf, 16, sizeof (char *)); + assert (fxbuf); + posix_memalign ((void **) fxbuf, 16, 512); + assert (*fxbuf); #endif - { - error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg; - } else { - - memset (fxbuf, 0, 512); - - asm volatile ( - "fxsave (%0)" - : - : "r" (fxbuf) - : "memory" - ); - - uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]); - - /* if the mask is zero, set its default value (from intel specs) */ - - if (mxcsr_mask == 0) { - mxcsr_mask = 0xffbf; - } - - if (mxcsr_mask & (1<<6)) { - _flags = Flags (_flags | HasDenormalsAreZero); - } - - free (fxbuf); + + memset (*fxbuf, 0, 512); + + asm volatile ( + "fxsave (%0)" + : + : "r" (*fxbuf) + : "memory" + ); + + uint32_t mxcsr_mask = *((uint32_t*) &((*fxbuf)[28])); + + /* if the mask is zero, set its default value (from intel specs) */ + + if (mxcsr_mask == 0) { + mxcsr_mask = 0xffbf; } + + if (mxcsr_mask & (1<<6)) { + _flags = Flags (_flags | HasDenormalsAreZero); + } + + free (*fxbuf); + free (fxbuf); } #endif } @@ -108,3 +141,7 @@ FPU::FPU () FPU::~FPU () { } + +#else // COMPILER_MSVC + const char* pbd_fpu = "pbd/msvc/fpu.cc takes precedence over this file"; +#endif // COMPILER_MSVC