mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Add a cpp-y, more fine grained version of fenv.h: FPControl.h
This allows direct inlining and hides away some assembly and bit-fiddling when manipulating the floating point environment. This only implements the x87/SSE versions, as of now.
This commit is contained in:
parent
9aa4958234
commit
6d9bc87903
Notes:
sideshowbarker
2024-07-17 11:11:49 +09:00
Author: https://github.com/Hendiadyoin1 Commit: https://github.com/SerenityOS/serenity/commit/6d9bc87903 Pull-request: https://github.com/SerenityOS/serenity/pull/13573 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/gmta Reviewed-by: https://github.com/kleinesfilmroellchen ✅ Reviewed-by: https://github.com/timschumi
1 changed files with 124 additions and 0 deletions
124
AK/FPControl.h
Normal file
124
AK/FPControl.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Leon Albrecht <leon.a@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
|
||||
// FIXME: Add equivalent datastructures for aarch64
|
||||
VALIDATE_IS_X86();
|
||||
|
||||
namespace AK {
|
||||
|
||||
enum class RoundingMode : u8 {
|
||||
NEAREST = 0b00,
|
||||
DOWN = 0b01,
|
||||
UP = 0b10,
|
||||
TRUNC = 0b11
|
||||
};
|
||||
|
||||
union X87ControlWord {
|
||||
u16 cw;
|
||||
struct {
|
||||
u16 mask_invalid : 1; // IM
|
||||
u16 mask_denorm : 1; // DM
|
||||
u16 mask_zero_div : 1; // ZM
|
||||
u16 mask_overflow : 1; // OM
|
||||
u16 mask_underflow : 1; // UM
|
||||
u16 mask_precision : 1; // PM
|
||||
u16 : 2; // unused
|
||||
u16 precision : 2; // PC
|
||||
RoundingMode rounding_control : 2; // RC
|
||||
u16 infinity_control : 1; // X
|
||||
u16 : 3; // unused
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(X87ControlWord) == sizeof(u16));
|
||||
|
||||
union MXCSR {
|
||||
u32 mxcsr;
|
||||
struct {
|
||||
u32 invalid_operation_flag : 1; // IE
|
||||
u32 denormal_operation_flag : 1; // DE
|
||||
u32 divide_by_zero_flag : 1; // ZE
|
||||
u32 overflow_flag : 1; // OE
|
||||
u32 underflow_flag : 1; // UE
|
||||
u32 precision_flag : 1; // PE
|
||||
u32 denormals_are_zero : 1; // DAZ
|
||||
u32 invalid_operation_mask : 1; // IM
|
||||
u32 denormal_operation_mask : 1; // DM
|
||||
u32 divide_by_zero_mask : 1; // ZM
|
||||
u32 overflow_mask : 1; // OM
|
||||
u32 underflow_mask : 1; // UM
|
||||
u32 precision_mask : 1; // PM
|
||||
RoundingMode rounding_control : 2; // RC
|
||||
u32 flush_to_zero : 1; // FTZ
|
||||
u32 __reserved : 16;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(MXCSR) == sizeof(u32));
|
||||
|
||||
ALWAYS_INLINE X87ControlWord get_cw_x87()
|
||||
{
|
||||
X87ControlWord control_word;
|
||||
asm("fnstcw %0"
|
||||
: "=m"(control_word));
|
||||
return control_word;
|
||||
}
|
||||
ALWAYS_INLINE void set_cw_x87(X87ControlWord control_word)
|
||||
{
|
||||
asm("fldcw %0" ::"m"(control_word));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE MXCSR get_mxcsr()
|
||||
{
|
||||
MXCSR mxcsr;
|
||||
asm("stmxcsr %0"
|
||||
: "=m"(mxcsr));
|
||||
return mxcsr;
|
||||
}
|
||||
ALWAYS_INLINE void set_mxcsr(MXCSR mxcsr)
|
||||
{
|
||||
asm("ldmxcsr %0" ::"m"(mxcsr));
|
||||
}
|
||||
|
||||
class X87RoundingModeScope {
|
||||
public:
|
||||
X87RoundingModeScope(RoundingMode rounding_mode)
|
||||
{
|
||||
m_cw = get_cw_x87();
|
||||
auto cw = m_cw;
|
||||
cw.rounding_control = rounding_mode;
|
||||
set_cw_x87(cw);
|
||||
}
|
||||
~X87RoundingModeScope()
|
||||
{
|
||||
set_cw_x87(m_cw);
|
||||
}
|
||||
|
||||
private:
|
||||
X87ControlWord m_cw;
|
||||
};
|
||||
|
||||
class SSERoundingModeScope {
|
||||
public:
|
||||
SSERoundingModeScope(RoundingMode rounding_mode)
|
||||
{
|
||||
m_mxcsr = get_mxcsr();
|
||||
auto mxcsr = m_mxcsr;
|
||||
mxcsr.rounding_control = rounding_mode;
|
||||
set_mxcsr(mxcsr);
|
||||
}
|
||||
~SSERoundingModeScope()
|
||||
{
|
||||
set_mxcsr(m_mxcsr);
|
||||
}
|
||||
|
||||
private:
|
||||
MXCSR m_mxcsr;
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in a new issue