1 #include <float.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include "opcodes.h"
5 
6 
7 #define L2F(insn,  initial, target,round)                                \
8 ({                                                                       \
9    register unsigned long source asm("2") =  initial;                    \
10    register typeof(target) _t asm("f0");                                 \
11    asm volatile(insn(round,0,0,2) :"=f" (_t):"d"(source));               \
12    _t;                                                                   \
13 })
14 
15 #define F2L(insn, initial, type, round, cc)                              \
16 ({                                                                       \
17    register type source asm("f0") =  initial;                            \
18    register unsigned long target asm ("2") = 0;                          \
19    asm volatile(insn(round,0,2,0)                                        \
20                 "ipm %1\n\t"                                             \
21                 "srl %1,28\n\t"                                          \
22  		:"=d" (target), "=d" (cc) :"f"(source):"cc");            \
23    target;                                                               \
24 })
25 
26 
27 #define DO_INSN_L2F32(insn, round)                                       \
28 ({                                                                       \
29    float f32;                                                            \
30    printf(#insn " %f\n", L2F(insn, 0, f32, round));                      \
31    printf(#insn " %f\n", L2F(insn, 1, f32, round));                      \
32    printf(#insn " %f\n", L2F(insn, 0xffffffffUL, f32, round));           \
33    printf(#insn " %f\n", L2F(insn, 0x80000000UL, f32, round));           \
34    printf(#insn " %f\n", L2F(insn, 0x7fffffffUL, f32, round));           \
35    printf(#insn " %f\n", L2F(insn, 0x100000000UL, f32, round));          \
36    printf(#insn " %f\n", L2F(insn, 0xffffffffffffffffUL, f32, round));   \
37    printf(#insn " %f\n", L2F(insn, 0x8000000000000000UL, f32, round));   \
38    printf(#insn " %f\n", L2F(insn, 0x7fffffffffffffffUL, f32, round));   \
39 })
40 
41 #define DO_INSN_L2F64(insn, round)                                       \
42 ({                                                                       \
43    double f64;                                                           \
44    printf(#insn " %f\n", L2F(insn, 0, f64, round));                      \
45    printf(#insn " %f\n", L2F(insn, 1, f64, round));                      \
46    printf(#insn " %f\n", L2F(insn, 0xffffffffUL, f64, round));           \
47    printf(#insn " %f\n", L2F(insn, 0x80000000UL, f64, round));           \
48    printf(#insn " %f\n", L2F(insn, 0x7fffffffUL, f64, round));           \
49    printf(#insn " %f\n", L2F(insn, 0x100000000UL, f64, round));          \
50    printf(#insn " %f\n", L2F(insn, 0xffffffffffffffffUL, f64, round));   \
51    printf(#insn " %f\n", L2F(insn, 0x8000000000000000UL, f64, round));   \
52    printf(#insn " %f\n", L2F(insn, 0x7fffffffffffffffUL, f64, round));   \
53 })
54 
55 #define DO_INSN_L2F128(insn, round)                                      \
56 ({                                                                       \
57    long double f128;                                                     \
58    printf(#insn " %Lf\n", L2F(insn, 0, f128, round));                    \
59    printf(#insn " %Lf\n", L2F(insn, 1, f128, round));                    \
60    printf(#insn " %Lf\n", L2F(insn, 0xffffffffUL, f128, round));         \
61    printf(#insn " %Lf\n", L2F(insn, 0x80000000UL, f128, round));         \
62    printf(#insn " %Lf\n", L2F(insn, 0x7fffffffUL, f128, round));         \
63    printf(#insn " %Lf\n", L2F(insn, 0x100000000UL, f128, round));        \
64    printf(#insn " %Lf\n", L2F(insn, 0xffffffffffffffffUL, f128, round)); \
65    printf(#insn " %Lf\n", L2F(insn, 0x8000000000000000UL, f128, round)); \
66    printf(#insn " %Lf\n", L2F(insn, 0x7fffffffffffffffUL, f128, round)); \
67 })
68 
69 #define DO_INSN_F2L(insn, round, type)                                   \
70 ({                                                                       \
71    int cc;                                                               \
72    printf(#insn " %lu ", F2L(insn, -1.1, type, round, cc));              \
73    printf("cc=%d\n", cc);                                                \
74    printf(#insn " %lu ", F2L(insn, 0, type, round, cc));                 \
75    printf("cc=%d\n", cc);                                                \
76    printf(#insn " %lu ", F2L(insn, 1, type, round, cc));                 \
77    printf("cc=%d\n", cc);                                                \
78    printf(#insn " %lu ", F2L(insn, 1.4, type, round, cc));               \
79    printf("cc=%d\n", cc);                                                \
80    printf(#insn " %lu ", F2L(insn, 1.5, type, round, cc));               \
81    printf("cc=%d\n", cc);                                                \
82    printf(#insn " %lu ", F2L(insn, 1.6, type, round, cc));               \
83    printf("cc=%d\n", cc);                                                \
84    printf(#insn " %lu ", F2L(insn, 1.6E+4, type, round, cc));            \
85    printf("cc=%d\n", cc);                                                \
86    printf(#insn " %lu ", F2L(insn, 1.6E+8, type, round, cc));            \
87    printf("cc=%d\n", cc);                                                \
88    printf(#insn " %lu ", F2L(insn, 1.6E+12, type, round, cc));           \
89    printf("cc=%d\n", cc);                                                \
90    printf(#insn " %lu ", F2L(insn, 1.6E+20, type, round, cc));           \
91    printf("cc=%d\n", cc);                                                \
92    printf(#insn " %lu ", F2L(insn, 1.6E+200, type, round, cc));          \
93    printf("cc=%d\n", cc);                                                \
94    printf(#insn " %lu ", F2L(insn, 1.6E+2000L, type, round, cc));        \
95    printf("cc=%d\n", cc);                                                \
96    printf(#insn " %lu ", F2L(insn, 1.6E-4, type, round, cc));            \
97    printf("cc=%d\n", cc);                                                \
98    printf(#insn " %lu ", F2L(insn, FLT_MIN, type, round, cc));           \
99    printf("cc=%d\n", cc);                                                \
100    printf(#insn " %lu ", F2L(insn, FLT_MAX, type, round, cc));           \
101    printf("cc=%d\n", cc);                                                \
102    printf(#insn " %lu ", F2L(insn, DBL_MIN, type, round, cc));           \
103    printf("cc=%d\n", cc);                                                \
104    printf(#insn " %lu ", F2L(insn, DBL_MAX, type, round, cc));           \
105    printf("cc=%d\n", cc);                                                \
106    printf(#insn " %lu ", F2L(insn, LDBL_MIN, type, round, cc));          \
107    printf("cc=%d\n", cc);                                                \
108    printf(#insn " %lu ", F2L(insn, LDBL_MAX, type, round, cc));          \
109    printf("cc=%d\n", cc);                                                \
110 })
111 
112 #define DO_L2F(round)                                                    \
113 ({                                                                       \
114    DO_INSN_L2F32(CELFBR, round);                                         \
115    DO_INSN_L2F32(CELGBR, round);                                         \
116    DO_INSN_L2F64(CDLFBR, round);                                         \
117    DO_INSN_L2F64(CDLGBR, round);                                         \
118    DO_INSN_L2F128(CXLFBR, round);                                        \
119    DO_INSN_L2F128(CXLGBR, round);                                        \
120 })
121 
122 #define DO_F2L(round)                                                    \
123 ({                                                                       \
124    DO_INSN_F2L(CLFEBR, round, float);                                    \
125    DO_INSN_F2L(CLGEBR, round, float);                                    \
126    DO_INSN_F2L(CLFDBR, round, double);                                   \
127    DO_INSN_F2L(CLGDBR, round, double);                                   \
128    DO_INSN_F2L(CLFXBR, round, long double);                              \
129    DO_INSN_F2L(CLGXBR, round, long double);                              \
130 })
131 
132 
main()133 int main()
134 {
135    assert(sizeof(long double) == 16);
136    DO_L2F(4);
137    DO_F2L(4);
138 
139    DO_L2F(5);
140    DO_F2L(5);
141 
142    DO_L2F(6);
143    DO_F2L(6);
144 
145    DO_L2F(7);
146    DO_F2L(7);
147 
148    return 0;
149 }
150