1#include <float.h>
2#include <stdio.h>
3#include <stdint.h>
4#include <inttypes.h>
5#include <limits.h>
6
7/* The following opcodes are tested:
8
9   Convert to fixed:    cfebr, cgebr, cfdbr, cgdbr
10   Convert from fixed:  cefbr, cdfbr, cegbr, cdgbr
11
12   We do not test rounding here. Just making sure the insn selector
13   picks the correct insn.
14*/
15
16#define I2F(insn, initial, target_type)                         \
17do {                                                            \
18   int64_t source = initial;                                    \
19   target_type target;                                          \
20   asm volatile(insn " %0,%1\n\t" :"=f" (target) :"d"(source)); \
21   printf(insn " %"PRId64" -> %f\n", source, target);           \
22} while (0)
23
24#define DO_INSN_I32_TO_F(insn, target_type)        \
25do {                                               \
26   printf("\n----- int32_t -> " #target_type "\n");\
27   I2F(insn,   0, target_type);                    \
28   I2F(insn,   1, target_type);                    \
29   I2F(insn,  -1, target_type);                    \
30   I2F(insn,  42, target_type);                    \
31   I2F(insn, SHRT_MAX, target_type);               \
32   I2F(insn, SHRT_MIN, target_type);               \
33   I2F(insn, INT_MAX, target_type);                \
34   I2F(insn, INT_MIN, target_type);                \
35} while (0)
36
37#define DO_INSN_I64_TO_F(insn, target_type)        \
38do {                                               \
39   printf("\n----- int64_t -> " #target_type "\n");\
40   I2F(insn,   0, target_type);                    \
41   I2F(insn,   1, target_type);                    \
42   I2F(insn,  -1, target_type);                    \
43   I2F(insn,  42, target_type);                    \
44   I2F(insn, SHRT_MAX, target_type);               \
45   I2F(insn, SHRT_MIN, target_type);               \
46   I2F(insn, INT_MAX, target_type);                \
47   I2F(insn, INT_MIN, target_type);                \
48   I2F(insn, LONG_MAX, target_type);               \
49   I2F(insn, LONG_MIN, target_type);               \
50} while (0)
51
52#define DO_I2F()                        \
53do {                                    \
54   DO_INSN_I32_TO_F("cefbr", float);    \
55   DO_INSN_I32_TO_F("cdfbr", double);   \
56   DO_INSN_I64_TO_F("cegbr", float);    \
57   DO_INSN_I64_TO_F("cdgbr", double);   \
58} while (0)
59
60
61#define F2I(insn, initial, source_type, target_type)               \
62do {                                                               \
63   int cc;                                                         \
64   source_type source = initial;                                   \
65   target_type target = 0;                                         \
66   asm volatile(insn " %0,0,%2\n\t"                                \
67                "ipm %1\n\t"                                       \
68                "srl %1,28\n\t"                                    \
69 		: "=d" (target), "=d" (cc) : "f"(source) : "cc");  \
70   printf(insn " %f -> %ld   cc = %d\n", source, (long)target, cc); \
71} while (0)
72
73#define DO_INSN_F32_TO_I(insn, type)          \
74do {                                          \
75   printf("\n----- float -> " #type "\n");    \
76   F2I(insn, -1.0f, float, type);             \
77   F2I(insn,  0.0f, float, type);             \
78   F2I(insn,  1.0f, float, type);             \
79   F2I(insn, 1.4f, float, type);              \
80   F2I(insn, 1.5f, float, type);              \
81   F2I(insn, 1.6f, float, type);              \
82   F2I(insn, 1.6E+4f, float, type);           \
83   F2I(insn, 1.6E+8f, float, type);           \
84   F2I(insn, 1.6E-4f, float, type);           \
85   F2I(insn, FLT_MAX, float, type);           \
86} while (0)
87
88#define DO_INSN_F64_TO_I(insn, type)          \
89do {                                          \
90   printf("\n----- double -> " #type "\n");   \
91   F2I(insn, -1.0, double, type);             \
92   F2I(insn,  0.0, double, type);             \
93   F2I(insn,  1.0, double, type);             \
94   F2I(insn, 1.4, double, type);              \
95   F2I(insn, 1.5, double, type);              \
96   F2I(insn, 1.6, double, type);              \
97   F2I(insn, 1.6E+4, double, type);           \
98   F2I(insn, 1.6E+8, double, type);           \
99   F2I(insn, 1.6E-4, double, type);           \
100   F2I(insn, FLT_MAX, double, type);          \
101   F2I(insn, DBL_MAX, double, type);          \
102} while (0)
103
104#define DO_F2I()                        \
105do {                                    \
106   DO_INSN_F32_TO_I("cfebr", int32_t);  \
107   DO_INSN_F32_TO_I("cgebr", int64_t);  \
108   DO_INSN_F64_TO_I("cfdbr", int32_t);  \
109   DO_INSN_F64_TO_I("cgdbr", int64_t);  \
110} while (0)
111
112
113int main()
114{
115   DO_I2F();
116   DO_F2I();
117
118   return 0;
119}
120