1 /** 2 * Copyright: Copyright Auburn Sounds 2015-2016 3 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 4 * Authors: Guillaume Piolat 5 */ 6 module dplug.core.fpcontrol; 7 8 version(X86) 9 version = isX86; 10 version(X86_64) 11 version = isX86; 12 13 /// This struct ensures that floating point is save/restored and set consistently in plugin callbacks. 14 struct FPControl 15 { 16 void initialize() nothrow @nogc 17 { 18 version(isX86) 19 { 20 // store SSE control word 21 sseState = getSSEControlState(); 22 setSSEControlState(0x9fff); // Flush denormals to zero + Denormals Are Zeros + all exception masked 23 24 // store FPU control word 25 fpuState = getFPUControlState(); 26 27 28 // masks all floating-point exceptions, sets rounding to nearest, and sets the x87 FPU precision to 64 bits 29 ushort control = 0x037f; 30 31 // Looking for problems? Unmask all errors. 32 //control = 0x0340; 33 34 // Looking for denormals only? This unmasks denormal creation and denormal use exceptions. 35 //control = 0x036d; 36 37 setFPUControlState(control); 38 } 39 } 40 41 ~this() nothrow @nogc 42 { 43 version(isX86) 44 { 45 // restore SSE2 LDMXCSR and STMXCSR load and write the MXCSR 46 setSSEControlState(sseState); 47 48 // restore FPU control word 49 setFPUControlState(fpuState); 50 } 51 } 52 53 version(isX86) 54 { 55 ushort fpuState; 56 uint sseState; 57 } 58 } 59 60 61 version(isX86) 62 { 63 version(D_InlineAsm_X86) 64 version = InlineX86Asm; 65 else version(D_InlineAsm_X86_64) 66 version = InlineX86Asm; 67 68 /// Gets FPU control register 69 ushort getFPUControlState() nothrow @nogc 70 { 71 version (InlineX86Asm) 72 { 73 short cont; 74 asm nothrow @nogc 75 { 76 xor EAX, EAX; 77 fstcw cont; 78 } 79 return cont; 80 } 81 else 82 static assert(0, "Unsupported"); 83 } 84 85 /// Sets FPU control register 86 void setFPUControlState(ushort newState) nothrow @nogc 87 { 88 // MAYDO: report that the naked version in Phobos is buggy on OSX 89 // it fills the control word with a random word which can create 90 // FP exceptions. 91 version (InlineX86Asm) 92 { 93 asm nothrow @nogc 94 { 95 fclex; 96 fldcw newState; 97 } 98 } 99 else 100 static assert(0, "Unsupported"); 101 } 102 103 /// Get SSE control register 104 uint getSSEControlState() @trusted nothrow @nogc 105 { 106 version (InlineX86Asm) 107 { 108 uint controlWord; 109 asm nothrow @nogc 110 { 111 stmxcsr controlWord; 112 } 113 return controlWord; 114 } 115 else 116 assert(0, "Not yet supported"); 117 } 118 119 /// Sets SSE control register 120 void setSSEControlState(uint controlWord) @trusted nothrow @nogc 121 { 122 version (InlineX86Asm) 123 { 124 asm nothrow @nogc 125 { 126 ldmxcsr controlWord; 127 } 128 } 129 else 130 assert(0, "Not yet supported"); 131 } 132 } 133 134 unittest 135 { 136 137 FPControl control; 138 control.initialize(); 139 140 141 }