Skip to content

Commit e0c9a43

Browse files
committed
ieee 754: start section
1 parent 4da91c1 commit e0c9a43

File tree

3 files changed

+105
-1
lines changed

3 files changed

+105
-1
lines changed

README.adoc

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12063,7 +12063,7 @@ Particularly important numerical analysis instruction, that is used in particula
1206312063
* Dot product
1206412064
* Matrix multiplication
1206512065

12066-
FMA is so important that IEEE 754 specifies it with single precision drop compared to a separate add and multiply!
12066+
FMA is so important that <<ieee-754>> specifies it with single precision drop compared to a separate add and multiply!
1206712067

1206812068
Micro-op fun: http://stackoverflow.com/questions/28630864/how-is-fma-implemented
1206912069

@@ -12990,6 +12990,19 @@ Old floating point unit that you should likely not use anymore, prefer instead t
1299012990
** link:userland/arch/x86_64/fsqrt.S[] FSQRT: square root
1299112991
** link:userland/arch/x86_64/fxch.S[] FXCH: swap ST0 and another register
1299212992

12993+
The ST0-ST7 x87 FPU registers are actually 80-bits wide, this can be seen from GDB with:
12994+
12995+
....
12996+
i r st0 st1
12997+
....
12998+
12999+
By counting the number of hex digits, we have 20 digits instead of 16!
13000+
13001+
Instructions such as FLDL convert standard <<ieee-754>> 64-bit values from memory into this custom 80-bit format.
13002+
13003+
* https://stackoverflow.com/questions/3206101/extended-80-bit-double-floating-point-in-x87-not-sse2-we-dont-miss-it
13004+
* https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format
13005+
1299313006
==== x86 x87 FPU vs SIMD
1299413007

1299513008
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
1417714190

1417814191
2013.
1417914192

14193+
== IEEE 754
14194+
14195+
https://en.wikipedia.org/wiki/IEEE_754
14196+
14197+
Examples:
14198+
14199+
* link:userland/arch/x86_64/ieee754.S[]
14200+
* link:lkmc/float.h[]
14201+
* https://stackoverflow.com/questions/8341395/what-is-a-subnormal-floating-point-number/53203428#53203428
14202+
* https://stackoverflow.com/questions/18118408/what-is-difference-between-quiet-nan-and-signaling-nan/55648118#55648118
14203+
* https://stackoverflow.com/questions/2618059/in-java-what-does-nan-mean/55673220#55673220
14204+
1418014205
== Baremetal
1418114206

1418214207
Getting started at: <<baremetal-setup>>

lkmc/float.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef LKMC_FLOAT_H
2+
#define LKMC_FLOAT_H
3+
4+
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ieee-754 */
5+
6+
#define LKMC_FLOAT_64_SIGN_BITS 1
7+
#define LKMC_FLOAT_64_EXP_BITS 11
8+
#define LKMC_FLOAT_64_MANTISSA_BITS 52
9+
#define LKMC_FLOAT_64_EXP_BIAS ((1 << (LKMC_FLOAT_64_EXP_BITS - 1)) - 1)
10+
#define LKMC_FLOAT_64_EXP_INFINITY_BIASED ((1 << LKMC_FLOAT_64_EXP_BITS) - 1)
11+
#define LKMC_FLOAT_64_EXP_INFINITY (LKMC_FLOAT_64_EXP_INFINITY_BIASED - LKMC_FLOAT_64_EXP_BIAS)
12+
#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)
13+
#define LKMC_FLOAT_64_PLUS_INFINITY LKMC_FLOAT_64(0x0, LKMC_FLOAT_64_EXP_INFINITY, 0x0)
14+
#define LKMC_FLOAT_64_MINUS_INFINITY LKMC_FLOAT_64(0x1, LKMC_FLOAT_64_EXP_INFINITY, 0x0)
15+
#define LKMC_FLOAT_64_QNAN(x) LKMC_FLOAT_64(0x0, LKMC_FLOAT_64_EXP_INFINITY, (x) | (1 << (LKMC_FLOAT_64_MANTISSA_BITS - 1)))
16+
#define LKMC_FLOAT_64_QNAN_DEFAULT LKMC_FLOAT_64_QNAN(1 << (LKMC_FLOAT_64_MANTISSA_BITS - 2))
17+
#define LKMC_FLOAT_64_SNAN(x) LKMC_FLOAT_64(0x0, LKMC_FLOAT_64_EXP_INFINITY, x)
18+
#define LKMC_FLOAT_64_SNAN_DEFAULT LKMC_FLOAT_64_SNAN(1 << (LKMC_FLOAT_64_MANTISSA_BITS - 2))
19+
20+
#endif

userland/arch/x86_64/ieee754.S

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ieee-754 */
2+
3+
#include <lkmc.h>
4+
#include <lkmc/float.h>
5+
6+
.data
7+
double_1_5: .quad LKMC_FLOAT_64(0x0, 0x0, 0x8000000000000)
8+
double_2_5: .quad LKMC_FLOAT_64(0x0, 0x1, 0x4000000000000)
9+
double_4_0: .quad LKMC_FLOAT_64(0x0, 0x2, 0x0000000000000)
10+
double_minus_4_0: .quad LKMC_FLOAT_64(0x1, 0x2, 0x10000000000000)
11+
double_plus_infinity: .quad LKMC_FLOAT_64_PLUS_INFINITY
12+
double_nan: .quad LKMC_FLOAT_64_QNAN_DEFAULT
13+
double_ref_1_5: .double 1.5
14+
double_ref_2_5: .double 2.5
15+
double_ref_4_0: .double 4.0
16+
double_ref_minus_4_0: .double -4.0
17+
double_ref_plus_infinity: .double inf
18+
double_ref_nan: .double nan
19+
LKMC_PROLOGUE
20+
/* Check that our macros are correct. */
21+
LKMC_ASSERT_EQ(double_1_5, double_ref_1_5)
22+
LKMC_ASSERT_EQ(double_2_5, double_ref_2_5)
23+
LKMC_ASSERT_EQ(double_4_0, double_ref_4_0)
24+
LKMC_ASSERT_EQ(double_minus_4_0, double_ref_minus_4_0)
25+
LKMC_ASSERT_EQ(double_plus_infinity, double_ref_plus_infinity)
26+
/* TODO: GAS nan is a different NaN: 0x7FFFFFFF */
27+
/*LKMC_ASSERT_EQ(double_nan, double_ref_nan)*/
28+
29+
/* x87 80-bit FPU: https://github.com/cirosantilli/linux-kernel-module-cheat#x86-x87-fpu-instructions */
30+
31+
/* 1.5 + 2.5 == 4.0. */
32+
fldl double_1_5
33+
fldl double_2_5
34+
faddp %st, %st(1)
35+
fldl double_4_0
36+
fcomip %st(1)
37+
LKMC_ASSERT(je)
38+
39+
/* 4.0 + -4.0 == 0.0. */
40+
fldl double_minus_4_0
41+
faddp %st, %st(1)
42+
fldz
43+
fcomip %st(1)
44+
LKMC_ASSERT(je)
45+
46+
/* 0.0 + inf == inf */
47+
fldl double_plus_infinity
48+
faddp %st, %st(1)
49+
fldl double_plus_infinity
50+
fcomip %st(1)
51+
LKMC_ASSERT(je)
52+
53+
/* inf + nan == nan */
54+
fldl double_nan
55+
faddp %st, %st(1)
56+
fldl double_nan
57+
fcomip %st(1)
58+
LKMC_ASSERT(je)
59+
LKMC_EPILOGUE

0 commit comments

Comments
 (0)