Created
June 24, 2025 15:40
-
-
Save jakubtomsu/361f9319f73ed0ae9c0e36df887226b9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package fp_exceptions | |
| import "core:log" | |
| when ODIN_OS == .Windows { | |
| foreign import libcmt "system:libcmt.lib" | |
| } | |
| @(default_calling_convention = "system") | |
| foreign libcmt { | |
| _controlfp_s :: proc(currentControl: ^u32, newControl: u32,mask: u32) -> i32 --- | |
| } | |
| // Set parameters of exceptions you want to enable to true | |
| fp_exceptions_set :: proc( | |
| invalid := false, | |
| zero_div := false, | |
| ) { | |
| cw: u32 | |
| _controlfp_s(&cw, 0, 0) | |
| // Note: setting the bit to 0 enables the exception | |
| if invalid { | |
| cw &= ~u32(_EM_INVALID) | |
| } else { | |
| cw |= u32(_EM_INVALID) | |
| } | |
| if zero_div { | |
| cw &= ~u32(_EM_ZERODIVIDE) | |
| } else { | |
| cw |= u32(_EM_ZERODIVIDE) | |
| } | |
| _controlfp_s(nil, cw, _MCW_EM) | |
| } | |
| fp_exceptions_log :: proc() { | |
| cw: u32 | |
| _controlfp_s(&cw, 0, 0) | |
| if 0 == cw & _EM_INEXACT do log.info("FP except: EM_INEXACT: inexact (precision)") | |
| if 0 == cw & _EM_UNDERFLOW do log.info("FP except: EM_UNDERFLOW: underflow") | |
| if 0 == cw & _EM_OVERFLOW do log.info("FP except: EM_OVERFLOW: overflow") | |
| if 0 == cw & _EM_ZERODIVIDE do log.info("FP except: EM_ZERODIVIDE: zero divide") | |
| if 0 == cw & _EM_INVALID do log.info("FP except: EM_INVALID: invalid") | |
| if 0 != cw & _RC_NEAR do log.info("FP except: RC_NEAR: near") | |
| if 0 != cw & _RC_DOWN do log.info("FP except: RC_DOWN: down") | |
| if 0 != cw & _RC_UP do log.info("FP except: RC_UP: up") | |
| if 0 != cw & _RC_CHOP do log.info("FP except: RC_CHOP: chop") | |
| if 0 != cw & _IC_AFFINE do log.info("FP except: IC_AFFINE: affine") | |
| if 0 != cw & _IC_PROJECTIVE do log.info("FP except: IC_PROJECTIVE: projective") | |
| if 0 != cw & _DN_SAVE do log.info("FP except: DN_SAVE: save denormal results and operands") | |
| if 0 != cw & _DN_FLUSH do log.info("FP except: DN_FLUSH: flush denormal results and operands to zero") | |
| } | |
| // New Control Bit that specifies the ambiguity in control word. | |
| _EM_AMBIGUIOUS :: 0x80000000 // For backwards compatibility | |
| _EM_AMBIGUOUS :: 0x80000000 | |
| // Abstract User Control Word Mask and bit definitions | |
| _MCW_EM :: 0x0008001f // Interrupt Exception Masks | |
| _EM_INEXACT :: 0x00000001 // inexact (precision) | |
| _EM_UNDERFLOW :: 0x00000002 // underflow | |
| _EM_OVERFLOW :: 0x00000004 // overflow | |
| _EM_ZERODIVIDE :: 0x00000008 // zero divide | |
| _EM_INVALID :: 0x00000010 // invalid | |
| _EM_DENORMAL :: 0x00080000 // Denormal exception mask (_control87 only) | |
| _MCW_RC :: 0x00000300 // Rounding Control | |
| _RC_NEAR :: 0x00000000 // near | |
| _RC_DOWN :: 0x00000100 // down | |
| _RC_UP :: 0x00000200 // up | |
| _RC_CHOP :: 0x00000300 // chop | |
| // i386 specific definitions | |
| _MCW_PC :: 0x00030000 // Precision Control | |
| _PC_64 :: 0x00000000 // 64 bits | |
| _PC_53 :: 0x00010000 // 53 bits | |
| _PC_24 :: 0x00020000 // 24 bits | |
| _MCW_IC :: 0x00040000 // Infinity Control | |
| _IC_AFFINE :: 0x00040000 // affine | |
| _IC_PROJECTIVE :: 0x00000000 // projective | |
| // RISC specific definitions | |
| _MCW_DN :: 0x03000000 // Denormal Control | |
| _DN_SAVE :: 0x00000000 // save denormal results and operands | |
| _DN_FLUSH :: 0x01000000 // flush denormal results and operands to zero | |
| _DN_FLUSH_OPERANDS_SAVE_RESULTS :: 0x02000000 // flush operands to zero and save results | |
| _DN_SAVE_OPERANDS_FLUSH_RESULTS :: 0x03000000 // save operands and flush results to zero |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment