Skip to content

Instantly share code, notes, and snippets.

@simonbyrne
Last active August 29, 2015 14:09
Show Gist options
  • Save simonbyrne/9c1e4704be46b66b1485 to your computer and use it in GitHub Desktop.
Save simonbyrne/9c1e4704be46b66b1485 to your computer and use it in GitHub Desktop.
function getmxcsr()
Base.llvmcall("""%ptr = alloca i32
call void @llvm.x86.sse.stmxcsr(i32 * %ptr)
%curval = load i32 * %ptr
ret i32 %curval""", UInt32, ())
end
function setmxcsr(u::UInt32)
Base.llvmcall("""%ptr = alloca i32
store i32 %0, i32 * %ptr
call void @llvm.x86.sse.ldmxcsr(i32 * %ptr)
ret void""", Void, (UInt32,),u)
end
# from
# Intel® 64 and IA-32 Architectures Software Developer’s Manual
# Chapter 10.2.3 MXCSR Control and Status Register
# 0b0_0_00_000000_0_000000
# x 17 (15) flush denormals to zero
# xx 18-19 (13-14) rounding mode
# xxxxxx 20-25 (7-12) exception mask bits
# x 26 (6) denomals are zeros
# xxxxxx 27-32 (0-5) exception sticky flags
const FE_EXCEPT_INVALID = 0b0_0_00_000000_0_000001
const FE_EXCEPT_DENORMAL = 0b0_0_00_000000_0_000010
const FE_EXCEPT_DIVBYZERO = 0b0_0_00_000000_0_000100
const FE_EXCEPT_OVERFLOW = 0b0_0_00_000000_0_001000
const FE_EXCEPT_UNDERFLOW = 0b0_0_00_000000_0_010000
const FE_EXCEPT_INEXACT = 0b0_0_00_000000_0_100000
const FE_MASK_INVALID = 0b0_0_00_000001_0_000000
const FE_MASK_DENORMAL = 0b0_0_00_000010_0_000000
const FE_MASK_DIVBYZERO = 0b0_0_00_000100_0_000000
const FE_MASK_OVERFLOW = 0b0_0_00_001000_0_000000
const FE_MASK_UNDERFLOW = 0b0_0_00_010000_0_000000
const FE_MASK_INEXACT = 0b0_0_00_100000_0_000000
const ROUNDNEAREST = 0b0_0_00_000000_0_000000
const ROUNDDOWN = 0b0_0_01_000000_0_000000
const ROUNDUP = 0b0_0_10_000000_0_000000
const ROUNDTOZERO = 0b0_0_11_000000_0_000000
const ROUNDMASK = ROUNDNEAREST | ROUNDUP | ROUNDDOWN | ROUNDTOZERO
function decmx(u::UInt32)
b = bits(u)
println("Flags: ",b[27:32])
println("Den = 0: ",b[26])
println("Masks: ",b[20:25])
println("Rounding: ",b[18:19])
println("Flush den: ",b[17])
end
# need to run methods a couple of times (ignore errors) to declare intrinsics
# see https://github.com/JuliaLang/julia/pull/8740
getmxcsr()
getmxcsr()
u = getmxcsr()
setmxcsr(u)
setmxcsr(u)
1.0/0.0
0.0/0.0
ccall((:sin,Base.Math.libm),Float64,(Float64,),Inf)
setmxcsr(u & ~FE_MASK_INVALID) # disable invalid mask
1.0/0.0
0.0/0.0
ccall((:sin,Base.Math.libm),Float64,(Float64,),Inf)
setmxcsr(u) # reset mask
@simonbyrne
Copy link
Author

Last few lines give:

julia> 1.0/0.0
Inf

julia> 0.0/0.0
NaN

julia> ccall((:sin,Base.Math.libm),Float64,(Float64,),Inf)
NaN

julia> setmxcsr(u & ~FE_MASK_INVALID) # disable invalid mask

julia> 1.0/0.0
Inf

julia> 0.0/0.0
ERROR: integer division error
 in / at ./float.jl:126
 in / at /Users/simon/src/julia/usr/lib/julia/sys.dylib

julia> ccall((:sin,Base.Math.libm),Float64,(Float64,),Inf)
ERROR: integer division error
 in anonymous at no file

julia> setmxcsr(u) # reset mask

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment