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