1 | #include <cstdint> |
2 | |
3 | struct alignas(16) float80_raw { |
4 | uint64_t mantissa; |
5 | uint16_t sign_exp; |
6 | }; |
7 | |
8 | int main() { |
9 | float80_raw st[] = { |
10 | {.mantissa: 0x8000000000000000, .sign_exp: 0x4000}, // +2.0 |
11 | {.mantissa: 0x3f00000000000000, .sign_exp: 0x0000}, // 1.654785e-4932 (denormal) |
12 | {.mantissa: 0x0000000000000000, .sign_exp: 0x0000}, // +0 |
13 | {.mantissa: 0x0000000000000000, .sign_exp: 0x8000}, // -0 |
14 | {.mantissa: 0x8000000000000000, .sign_exp: 0x7fff}, // +inf |
15 | {.mantissa: 0x8000000000000000, .sign_exp: 0xffff}, // -inf |
16 | {.mantissa: 0xc000000000000000, .sign_exp: 0xffff}, // nan |
17 | // st7 will be freed to test tag word better |
18 | {.mantissa: 0x0000000000000000, .sign_exp: 0x0000}, // +0 |
19 | }; |
20 | |
21 | // unmask divide-by-zero exception |
22 | uint16_t cw = 0x037b; |
23 | // used as single-precision float |
24 | uint32_t zero = 0; |
25 | |
26 | asm volatile( |
27 | "finit\n\t" |
28 | "fldcw %1\n\t" |
29 | // load on stack in reverse order to make the result easier to read |
30 | "fldt 0x70(%0)\n\t" |
31 | "fldt 0x60(%0)\n\t" |
32 | "fldt 0x50(%0)\n\t" |
33 | "fldt 0x40(%0)\n\t" |
34 | "fldt 0x30(%0)\n\t" |
35 | "fldt 0x20(%0)\n\t" |
36 | "fldt 0x10(%0)\n\t" |
37 | "fldt 0x00(%0)\n\t" |
38 | // free st7 |
39 | "ffree %%st(7)\n\t" |
40 | // this should trigger a divide-by-zero |
41 | "fdivs (%2)\n\t" |
42 | "int3\n\t" |
43 | : |
44 | : "a" (st), "m" (cw), "b" (&zero) |
45 | : "st" |
46 | ); |
47 | |
48 | return 0; |
49 | } |
50 | |