ieee 754: start section

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-06-29 00:00:02 +00:00
parent 4da91c1e51
commit e0c9a43aae
3 changed files with 105 additions and 1 deletions

View File

@@ -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
View 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

View 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