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) \
17 do { \
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) \
25 do { \
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) \
38 do { \
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() \
53 do { \
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) \
62 do { \
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) \
74 do { \
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) \
89 do { \
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() \
105 do { \
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
main()113 int main()
114 {
115 DO_I2F();
116 DO_F2I();
117
118 return 0;
119 }
120