1 | #include <stdlib.h> |
2 | #include <soft-fp.h> |
3 | #include <quad.h> |
4 | |
5 | /* Helpers for the Ots functions which receive long double arguments |
6 | in two integer registers, and return values in $16+$17. */ |
7 | |
8 | #define AXP_UNPACK_RAW_Q(X, val) \ |
9 | do { \ |
10 | union _FP_UNION_Q _flo; \ |
11 | _flo.longs.a = val##l; \ |
12 | _flo.longs.b = val##h; \ |
13 | FP_UNPACK_RAW_QP(X, &_flo); \ |
14 | } while (0) |
15 | |
16 | #define AXP_UNPACK_SEMIRAW_Q(X, val) \ |
17 | do { \ |
18 | union _FP_UNION_Q _flo; \ |
19 | _flo.longs.a = val##l; \ |
20 | _flo.longs.b = val##h; \ |
21 | FP_UNPACK_SEMIRAW_QP(X, &_flo); \ |
22 | } while (0) |
23 | |
24 | #define AXP_UNPACK_Q(X, val) \ |
25 | do { \ |
26 | AXP_UNPACK_RAW_Q(X, val); \ |
27 | _FP_UNPACK_CANONICAL(Q, 2, X); \ |
28 | } while (0) |
29 | |
30 | #define AXP_PACK_RAW_Q(val, X) FP_PACK_RAW_QP(&val##_flo, X) |
31 | |
32 | #define AXP_PACK_SEMIRAW_Q(val, X) \ |
33 | do { \ |
34 | _FP_PACK_SEMIRAW(Q, 2, X); \ |
35 | AXP_PACK_RAW_Q(val, X); \ |
36 | } while (0) |
37 | |
38 | #define AXP_PACK_Q(val, X) \ |
39 | do { \ |
40 | _FP_PACK_CANONICAL(Q, 2, X); \ |
41 | AXP_PACK_RAW_Q(val, X); \ |
42 | } while (0) |
43 | |
44 | #define AXP_DECL_RETURN_Q(X) union _FP_UNION_Q X##_flo |
45 | |
46 | /* ??? We don't have a real way to tell the compiler that we're wanting |
47 | to return values in $16+$17. Instead use a volatile asm to make sure |
48 | that the values are live, and just hope that nothing kills the values |
49 | in between here and the end of the function. */ |
50 | #define AXP_RETURN_Q(X) \ |
51 | do { \ |
52 | register long r16 __asm__("16") = X##_flo.longs.a; \ |
53 | register long r17 __asm__("17") = X##_flo.longs.b; \ |
54 | asm volatile ("" : : "r"(r16), "r"(r17)); \ |
55 | } while (0) |
56 | |