1 /** 2 Save/Restore floating-point control words, so that 3 rounding-mode doesn't change wildly in a shared library. 4 5 Copyright: Guillaume Piolat 2015-2016. 6 License: http://www.boost.org/LICENSE_1_0.txt 7 */ 8 module dplug.core.fpcontrol; 9 10 version(X86) 11 version = isX86; 12 version(X86_64) 13 version = isX86; 14 15 import inteli.xmmintrin; 16 17 nothrow @nogc: 18 19 /** 20 This struct ensures that floating point is save/restored 21 and set consistently in plugin callbacks. 22 */ 23 struct FPControl 24 { 25 nothrow @nogc: 26 void initialize() 27 { 28 // Save and set control word. This works because 29 // intel-intrinsics emulate that control word for 30 // ARM. 31 { 32 // Get current SSE control word 33 storedMXCSR = _mm_getcsr(); 34 35 // Set current SSE control word: 36 // - Flush denormals to zero 37 // - Denormals Are Zeros 38 // - all exception masked 39 _mm_setcsr(0x9fff); 40 } 41 42 // There is a x86 specific path-here because x86 has 43 // a FPU control word in addition to the SSE control 44 // word. 45 version(isX86) 46 { 47 // store FPU control word 48 fpuState = getFPUControlState(); 49 50 // masks all floating-point exceptions, 51 // sets rounding to nearest, 52 // and sets the x87 FPU precision to 64 bits 53 ushort control = 0x037f; 54 55 // Very rarely useful debug options below: 56 57 // 1. Looking for problems? Unmask all errors. 58 //control = 0x0340; 59 60 // 2. Looking for denormals only? This unmasks 61 // denormal creation and denormal use 62 // exceptions. 63 //control = 0x036d; 64 65 setFPUControlState(control); 66 } 67 } 68 69 ~this() 70 { 71 _mm_setcsr(storedMXCSR); 72 73 version(isX86) 74 { 75 // restore FPU control word 76 setFPUControlState(fpuState); 77 } 78 } 79 80 version(isX86) 81 { 82 ushort fpuState; 83 } 84 uint storedMXCSR; 85 } 86 87 88 version(isX86) 89 { 90 version(D_InlineAsm_X86) 91 version = InlineX86Asm; 92 else version(D_InlineAsm_X86_64) 93 version = InlineX86Asm; 94 95 ushort getFPUControlState() 96 { 97 version (InlineX86Asm) 98 { 99 short cont; 100 asm nothrow @nogc 101 { 102 xor EAX, EAX; 103 fstcw cont; 104 } 105 return cont; 106 } 107 else 108 static assert(0); 109 } 110 111 void setFPUControlState(ushort newState) 112 { 113 version (InlineX86Asm) 114 { 115 asm nothrow @nogc 116 { 117 fclex; 118 fldcw newState; 119 } 120 } 121 else 122 static assert(0); 123 } 124 } 125