mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
ieee 754: start section
This commit is contained in:
27
README.adoc
27
README.adoc
@@ -12063,7 +12063,7 @@ Particularly important numerical analysis instruction, that is used in particula
|
||||
* Dot product
|
||||
* Matrix multiplication
|
||||
|
||||
FMA is so important that IEEE 754 specifies it with single precision drop compared to a separate add and multiply!
|
||||
FMA is so important that <<ieee-754>> specifies it with single precision drop compared to a separate add and multiply!
|
||||
|
||||
Micro-op fun: http://stackoverflow.com/questions/28630864/how-is-fma-implemented
|
||||
|
||||
@@ -12990,6 +12990,19 @@ Old floating point unit that you should likely not use anymore, prefer instead t
|
||||
** link:userland/arch/x86_64/fsqrt.S[] FSQRT: square root
|
||||
** link:userland/arch/x86_64/fxch.S[] FXCH: swap ST0 and another register
|
||||
|
||||
The ST0-ST7 x87 FPU registers are actually 80-bits wide, this can be seen from GDB with:
|
||||
|
||||
....
|
||||
i r st0 st1
|
||||
....
|
||||
|
||||
By counting the number of hex digits, we have 20 digits instead of 16!
|
||||
|
||||
Instructions such as FLDL convert standard <<ieee-754>> 64-bit values from memory into this custom 80-bit format.
|
||||
|
||||
* https://stackoverflow.com/questions/3206101/extended-80-bit-double-floating-point-in-x87-not-sse2-we-dont-miss-it
|
||||
* https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format
|
||||
|
||||
==== x86 x87 FPU vs SIMD
|
||||
|
||||
http://stackoverflow.com/questions/1844669/benefits-of-x87-over-sse
|
||||
@@ -14177,6 +14190,18 @@ http://infocenter.arm.com/help/topic/com.arm.doc.ddi0438i/DDI0438I_cortex_a15_r4
|
||||
|
||||
2013.
|
||||
|
||||
== IEEE 754
|
||||
|
||||
https://en.wikipedia.org/wiki/IEEE_754
|
||||
|
||||
Examples:
|
||||
|
||||
* link:userland/arch/x86_64/ieee754.S[]
|
||||
* link:lkmc/float.h[]
|
||||
* https://stackoverflow.com/questions/8341395/what-is-a-subnormal-floating-point-number/53203428#53203428
|
||||
* https://stackoverflow.com/questions/18118408/what-is-difference-between-quiet-nan-and-signaling-nan/55648118#55648118
|
||||
* https://stackoverflow.com/questions/2618059/in-java-what-does-nan-mean/55673220#55673220
|
||||
|
||||
== Baremetal
|
||||
|
||||
Getting started at: <<baremetal-setup>>
|
||||
|
||||
20
lkmc/float.h
Normal file
20
lkmc/float.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef LKMC_FLOAT_H
|
||||
#define LKMC_FLOAT_H
|
||||
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ieee-754 */
|
||||
|
||||
#define LKMC_FLOAT_64_SIGN_BITS 1
|
||||
#define LKMC_FLOAT_64_EXP_BITS 11
|
||||
#define LKMC_FLOAT_64_MANTISSA_BITS 52
|
||||
#define LKMC_FLOAT_64_EXP_BIAS ((1 << (LKMC_FLOAT_64_EXP_BITS - 1)) - 1)
|
||||
#define LKMC_FLOAT_64_EXP_INFINITY_BIASED ((1 << LKMC_FLOAT_64_EXP_BITS) - 1)
|
||||
#define LKMC_FLOAT_64_EXP_INFINITY (LKMC_FLOAT_64_EXP_INFINITY_BIASED - LKMC_FLOAT_64_EXP_BIAS)
|
||||
#define LKMC_FLOAT_64(sign, exp, mantissa) ((((sign << LKMC_FLOAT_64_EXP_BITS) | exp + LKMC_FLOAT_64_EXP_BIAS) << LKMC_FLOAT_64_MANTISSA_BITS) | mantissa)
|
||||
#define LKMC_FLOAT_64_PLUS_INFINITY LKMC_FLOAT_64(0x0, LKMC_FLOAT_64_EXP_INFINITY, 0x0)
|
||||
#define LKMC_FLOAT_64_MINUS_INFINITY LKMC_FLOAT_64(0x1, LKMC_FLOAT_64_EXP_INFINITY, 0x0)
|
||||
#define LKMC_FLOAT_64_QNAN(x) LKMC_FLOAT_64(0x0, LKMC_FLOAT_64_EXP_INFINITY, (x) | (1 << (LKMC_FLOAT_64_MANTISSA_BITS - 1)))
|
||||
#define LKMC_FLOAT_64_QNAN_DEFAULT LKMC_FLOAT_64_QNAN(1 << (LKMC_FLOAT_64_MANTISSA_BITS - 2))
|
||||
#define LKMC_FLOAT_64_SNAN(x) LKMC_FLOAT_64(0x0, LKMC_FLOAT_64_EXP_INFINITY, x)
|
||||
#define LKMC_FLOAT_64_SNAN_DEFAULT LKMC_FLOAT_64_SNAN(1 << (LKMC_FLOAT_64_MANTISSA_BITS - 2))
|
||||
|
||||
#endif
|
||||
59
userland/arch/x86_64/ieee754.S
Normal file
59
userland/arch/x86_64/ieee754.S
Normal file
@@ -0,0 +1,59 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ieee-754 */
|
||||
|
||||
#include <lkmc.h>
|
||||
#include <lkmc/float.h>
|
||||
|
||||
.data
|
||||
double_1_5: .quad LKMC_FLOAT_64(0x0, 0x0, 0x8000000000000)
|
||||
double_2_5: .quad LKMC_FLOAT_64(0x0, 0x1, 0x4000000000000)
|
||||
double_4_0: .quad LKMC_FLOAT_64(0x0, 0x2, 0x0000000000000)
|
||||
double_minus_4_0: .quad LKMC_FLOAT_64(0x1, 0x2, 0x10000000000000)
|
||||
double_plus_infinity: .quad LKMC_FLOAT_64_PLUS_INFINITY
|
||||
double_nan: .quad LKMC_FLOAT_64_QNAN_DEFAULT
|
||||
double_ref_1_5: .double 1.5
|
||||
double_ref_2_5: .double 2.5
|
||||
double_ref_4_0: .double 4.0
|
||||
double_ref_minus_4_0: .double -4.0
|
||||
double_ref_plus_infinity: .double inf
|
||||
double_ref_nan: .double nan
|
||||
LKMC_PROLOGUE
|
||||
/* Check that our macros are correct. */
|
||||
LKMC_ASSERT_EQ(double_1_5, double_ref_1_5)
|
||||
LKMC_ASSERT_EQ(double_2_5, double_ref_2_5)
|
||||
LKMC_ASSERT_EQ(double_4_0, double_ref_4_0)
|
||||
LKMC_ASSERT_EQ(double_minus_4_0, double_ref_minus_4_0)
|
||||
LKMC_ASSERT_EQ(double_plus_infinity, double_ref_plus_infinity)
|
||||
/* TODO: GAS nan is a different NaN: 0x7FFFFFFF */
|
||||
/*LKMC_ASSERT_EQ(double_nan, double_ref_nan)*/
|
||||
|
||||
/* x87 80-bit FPU: https://github.com/cirosantilli/linux-kernel-module-cheat#x86-x87-fpu-instructions */
|
||||
|
||||
/* 1.5 + 2.5 == 4.0. */
|
||||
fldl double_1_5
|
||||
fldl double_2_5
|
||||
faddp %st, %st(1)
|
||||
fldl double_4_0
|
||||
fcomip %st(1)
|
||||
LKMC_ASSERT(je)
|
||||
|
||||
/* 4.0 + -4.0 == 0.0. */
|
||||
fldl double_minus_4_0
|
||||
faddp %st, %st(1)
|
||||
fldz
|
||||
fcomip %st(1)
|
||||
LKMC_ASSERT(je)
|
||||
|
||||
/* 0.0 + inf == inf */
|
||||
fldl double_plus_infinity
|
||||
faddp %st, %st(1)
|
||||
fldl double_plus_infinity
|
||||
fcomip %st(1)
|
||||
LKMC_ASSERT(je)
|
||||
|
||||
/* inf + nan == nan */
|
||||
fldl double_nan
|
||||
faddp %st, %st(1)
|
||||
fldl double_nan
|
||||
fcomip %st(1)
|
||||
LKMC_ASSERT(je)
|
||||
LKMC_EPILOGUE
|
||||
Reference in New Issue
Block a user