xref: /openbmc/qemu/tests/tcg/ppc64/vsx_f2i_nan.c (revision adf798b3795edb2cc333579309937cc7bd889593)
1  #include <stdio.h>
2  #include "qemu/compiler.h"
3  
4  typedef vector float vsx_float32_vec_t;
5  typedef vector double vsx_float64_vec_t;
6  typedef vector signed int vsx_int32_vec_t;
7  typedef vector unsigned int vsx_uint32_vec_t;
8  typedef vector signed long long vsx_int64_vec_t;
9  typedef vector unsigned long long vsx_uint64_vec_t;
10  
11  #define DEFINE_VSX_F2I_FUNC(SRC_T, DEST_T, INSN)                       \
12  static inline vsx_##DEST_T##_vec_t                                     \
13      vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(vsx_##SRC_T##_vec_t v) \
14  {                                                                      \
15      vsx_##DEST_T##_vec_t result;                                       \
16      asm(#INSN " %x0, %x1" : "=wa" (result) : "wa" (v));                \
17      return result;                                                     \
18  }
19  
DEFINE_VSX_F2I_FUNC(float32,int32,xvcvspsxws)20  DEFINE_VSX_F2I_FUNC(float32, int32, xvcvspsxws)
21  DEFINE_VSX_F2I_FUNC(float32, uint32, xvcvspuxws)
22  DEFINE_VSX_F2I_FUNC(float32, int64, xvcvspsxds)
23  DEFINE_VSX_F2I_FUNC(float32, uint64, xvcvspuxds)
24  DEFINE_VSX_F2I_FUNC(float64, int32, xvcvdpsxws)
25  DEFINE_VSX_F2I_FUNC(float64, uint32, xvcvdpuxws)
26  DEFINE_VSX_F2I_FUNC(float64, int64, xvcvdpsxds)
27  DEFINE_VSX_F2I_FUNC(float64, uint64, xvcvdpuxds)
28  
29  static inline vsx_float32_vec_t vsx_float32_is_nan(vsx_float32_vec_t v)
30  {
31      vsx_float32_vec_t abs_v;
32      vsx_float32_vec_t result_mask;
33      const vsx_uint32_vec_t f32_pos_inf_bits = {0x7F800000U, 0x7F800000U,
34                                                 0x7F800000U, 0x7F800000U};
35  
36      asm("xvabssp %x0, %x1" : "=wa" (abs_v) : "wa" (v));
37      asm("vcmpgtuw %0, %1, %2"
38          : "=v" (result_mask)
39          : "v" (abs_v), "v" (f32_pos_inf_bits));
40      return result_mask;
41  }
42  
vsx_float64_is_nan(vsx_float64_vec_t v)43  static inline vsx_float64_vec_t vsx_float64_is_nan(vsx_float64_vec_t v)
44  {
45      vsx_float64_vec_t abs_v;
46      vsx_float64_vec_t result_mask;
47      const vsx_uint64_vec_t f64_pos_inf_bits = {0x7FF0000000000000ULL,
48                                                 0x7FF0000000000000ULL};
49  
50      asm("xvabsdp %x0, %x1" : "=wa" (abs_v) : "wa" (v));
51      asm("vcmpgtud %0, %1, %2"
52          : "=v" (result_mask)
53          : "v" (abs_v), "v" (f64_pos_inf_bits));
54      return result_mask;
55  }
56  
57  #define DEFINE_VSX_BINARY_LOGICAL_OP_INSN(LANE_TYPE, OP_NAME, OP_INSN)    \
58  static inline vsx_##LANE_TYPE##_vec_t vsx_##LANE_TYPE##_##OP_NAME(        \
59      vsx_##LANE_TYPE##_vec_t a, vsx_##LANE_TYPE##_vec_t b)                 \
60  {                                                                         \
61      vsx_##LANE_TYPE##_vec_t result;                                       \
62      asm(#OP_INSN " %x0, %x1, %x2" : "=wa" (result) : "wa" (a), "wa" (b)); \
63      return result;                                                        \
64  }
65  
DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32,logical_and,xxland)66  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_and, xxland)
67  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_and, xxland)
68  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_and, xxland)
69  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_and, xxland)
70  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_and, xxland)
71  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_and, xxland)
72  
73  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_andc, xxlandc)
74  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_andc, xxlandc)
75  
76  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_or, xxlor)
77  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_or, xxlor)
78  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_or, xxlor)
79  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_or, xxlor)
80  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_or, xxlor)
81  DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_or, xxlor)
82  
83  static inline vsx_int32_vec_t vsx_mask_out_float32_vec_to_int32_vec(
84      vsx_int32_vec_t v)
85  {
86      return v;
87  }
vsx_mask_out_float32_vec_to_uint32_vec(vsx_uint32_vec_t v)88  static inline vsx_uint32_vec_t vsx_mask_out_float32_vec_to_uint32_vec(
89      vsx_uint32_vec_t v)
90  {
91      return v;
92  }
vsx_mask_out_float32_vec_to_int64_vec(vsx_int64_vec_t v)93  static inline vsx_int64_vec_t vsx_mask_out_float32_vec_to_int64_vec(
94      vsx_int64_vec_t v)
95  {
96      return v;
97  }
vsx_mask_out_float32_vec_to_uint64_vec(vsx_uint64_vec_t v)98  static inline vsx_uint64_vec_t vsx_mask_out_float32_vec_to_uint64_vec(
99      vsx_uint64_vec_t v)
100  {
101      return v;
102  }
103  
vsx_mask_out_float64_vec_to_int32_vec(vsx_int32_vec_t v)104  static inline vsx_int32_vec_t vsx_mask_out_float64_vec_to_int32_vec(
105      vsx_int32_vec_t v)
106  {
107  #if HOST_BIG_ENDIAN
108      const vsx_int32_vec_t valid_lanes_mask = {-1, 0, -1, 0};
109  #else
110      const vsx_int32_vec_t valid_lanes_mask = {0, -1, 0, -1};
111  #endif
112  
113      return vsx_int32_logical_and(v, valid_lanes_mask);
114  }
115  
vsx_mask_out_float64_vec_to_uint32_vec(vsx_uint32_vec_t v)116  static inline vsx_uint32_vec_t vsx_mask_out_float64_vec_to_uint32_vec(
117      vsx_uint32_vec_t v)
118  {
119      return (vsx_uint32_vec_t)vsx_mask_out_float64_vec_to_int32_vec(
120          (vsx_int32_vec_t)v);
121  }
122  
vsx_mask_out_float64_vec_to_int64_vec(vsx_int64_vec_t v)123  static inline vsx_int64_vec_t vsx_mask_out_float64_vec_to_int64_vec(
124      vsx_int64_vec_t v)
125  {
126      return v;
127  }
vsx_mask_out_float64_vec_to_uint64_vec(vsx_uint64_vec_t v)128  static inline vsx_uint64_vec_t vsx_mask_out_float64_vec_to_uint64_vec(
129      vsx_uint64_vec_t v)
130  {
131      return v;
132  }
133  
print_vsx_float32_vec_elements(FILE * stream,vsx_float32_vec_t vec)134  static inline void print_vsx_float32_vec_elements(FILE *stream,
135                                                    vsx_float32_vec_t vec)
136  {
137      fprintf(stream, "%g, %g, %g, %g", (double)vec[0], (double)vec[1],
138              (double)vec[2], (double)vec[3]);
139  }
140  
print_vsx_float64_vec_elements(FILE * stream,vsx_float64_vec_t vec)141  static inline void print_vsx_float64_vec_elements(FILE *stream,
142                                                    vsx_float64_vec_t vec)
143  {
144      fprintf(stream, "%.17g, %.17g", vec[0], vec[1]);
145  }
146  
print_vsx_int32_vec_elements(FILE * stream,vsx_int32_vec_t vec)147  static inline void print_vsx_int32_vec_elements(FILE *stream,
148                                                  vsx_int32_vec_t vec)
149  {
150      fprintf(stream, "%d, %d, %d, %d", vec[0], vec[1], vec[2], vec[3]);
151  }
152  
print_vsx_uint32_vec_elements(FILE * stream,vsx_uint32_vec_t vec)153  static inline void print_vsx_uint32_vec_elements(FILE *stream,
154                                                   vsx_uint32_vec_t vec)
155  {
156      fprintf(stream, "%u, %u, %u, %u", vec[0], vec[1], vec[2], vec[3]);
157  }
158  
print_vsx_int64_vec_elements(FILE * stream,vsx_int64_vec_t vec)159  static inline void print_vsx_int64_vec_elements(FILE *stream,
160                                                  vsx_int64_vec_t vec)
161  {
162      fprintf(stream, "%lld, %lld", vec[0], vec[1]);
163  }
164  
print_vsx_uint64_vec_elements(FILE * stream,vsx_uint64_vec_t vec)165  static inline void print_vsx_uint64_vec_elements(FILE *stream,
166                                                   vsx_uint64_vec_t vec)
167  {
168      fprintf(stream, "%llu, %llu", vec[0], vec[1]);
169  }
170  
171  #define DEFINE_VSX_ALL_EQ_FUNC(LANE_TYPE, CMP_INSN)                   \
172  static inline int vsx_##LANE_TYPE##_all_eq(vsx_##LANE_TYPE##_vec_t a, \
173                                             vsx_##LANE_TYPE##_vec_t b) \
174  {                                                                     \
175      unsigned result;                                                  \
176      vsx_##LANE_TYPE##_vec_t is_eq_mask_vec;                           \
177      asm(#CMP_INSN ". %0, %2, %3\n\t"                                  \
178          "mfocrf %1, 2"                                                \
179          : "=v" (is_eq_mask_vec), "=r" (result)                        \
180          : "v" (a), "v" (b)                                            \
181          : "cr6");                                                     \
182      return (int)((result >> 7) & 1u);                                 \
183  }
184  
DEFINE_VSX_ALL_EQ_FUNC(int32,vcmpequw)185  DEFINE_VSX_ALL_EQ_FUNC(int32, vcmpequw)
186  DEFINE_VSX_ALL_EQ_FUNC(uint32, vcmpequw)
187  DEFINE_VSX_ALL_EQ_FUNC(int64, vcmpequd)
188  DEFINE_VSX_ALL_EQ_FUNC(uint64, vcmpequd)
189  
190  #define DEFINE_VSX_F2I_TEST_FUNC(SRC_T, DEST_T)                          \
191  static inline int test_vsx_conv_##SRC_T##_vec_to_##DEST_T##_vec(         \
192      vsx_##SRC_T##_vec_t src_v)                                           \
193  {                                                                        \
194      const vsx_##SRC_T##_vec_t is_nan_mask = vsx_##SRC_T##_is_nan(src_v); \
195      const vsx_##SRC_T##_vec_t nan_src_v =                                \
196          vsx_##SRC_T##_logical_and(src_v, is_nan_mask);                   \
197      const vsx_##SRC_T##_vec_t non_nan_src_v =                            \
198          vsx_##SRC_T##_logical_andc(src_v, is_nan_mask);                  \
199                                                                           \
200      const vsx_##DEST_T##_vec_t expected_result =                         \
201          vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec(                    \
202              vsx_##DEST_T##_logical_or(                                   \
203                  vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(nan_src_v),  \
204                  vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(             \
205                      non_nan_src_v)));                                    \
206      const vsx_##DEST_T##_vec_t actual_result =                           \
207          vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec(                    \
208              vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(src_v));         \
209      const int test_result =                                              \
210          vsx_##DEST_T##_all_eq(expected_result, actual_result);           \
211                                                                           \
212      if (unlikely(test_result == 0)) {                                    \
213          fputs("FAIL: Conversion of " #SRC_T " vector to " #DEST_T        \
214                " vector failed\n", stdout);                               \
215          fputs("Source values: ", stdout);                                \
216          print_vsx_##SRC_T##_vec_elements(stdout, src_v);                 \
217          fputs("\nExpected result: ", stdout);                            \
218          print_vsx_##DEST_T##_vec_elements(stdout, expected_result);      \
219          fputs("\nActual result: ", stdout);                              \
220          print_vsx_##DEST_T##_vec_elements(stdout, actual_result);        \
221          fputs("\n\n", stdout);                                           \
222      }                                                                    \
223                                                                           \
224      return test_result;                                                  \
225  }
226  
227  
228  DEFINE_VSX_F2I_TEST_FUNC(float32, int32)
229  DEFINE_VSX_F2I_TEST_FUNC(float32, uint32)
230  DEFINE_VSX_F2I_TEST_FUNC(float32, int64)
231  DEFINE_VSX_F2I_TEST_FUNC(float32, uint64)
232  DEFINE_VSX_F2I_TEST_FUNC(float64, int32)
233  DEFINE_VSX_F2I_TEST_FUNC(float64, uint32)
234  DEFINE_VSX_F2I_TEST_FUNC(float64, int64)
235  DEFINE_VSX_F2I_TEST_FUNC(float64, uint64)
236  
237  static inline vsx_int32_vec_t vsx_int32_vec_from_mask(int mask)
238  {
239      const vsx_int32_vec_t bits_to_test = {1, 2, 4, 8};
240      const vsx_int32_vec_t vec_mask = {mask, mask, mask, mask};
241      vsx_int32_vec_t result;
242  
243      asm("vcmpequw %0, %1, %2"
244          : "=v" (result)
245          : "v" (vsx_int32_logical_and(vec_mask, bits_to_test)),
246            "v" (bits_to_test));
247      return result;
248  }
249  
vsx_int64_vec_from_mask(int mask)250  static inline vsx_int64_vec_t vsx_int64_vec_from_mask(int mask)
251  {
252      const vsx_int64_vec_t bits_to_test = {1, 2};
253      const vsx_int64_vec_t vec_mask = {mask, mask};
254      vsx_int64_vec_t result;
255  
256      asm("vcmpequd %0, %1, %2"
257          : "=v" (result)
258          : "v" (vsx_int64_logical_and(vec_mask, bits_to_test)),
259            "v" (bits_to_test));
260      return result;
261  }
262  
main(void)263  int main(void)
264  {
265      const vsx_float32_vec_t f32_iota1 = {1.0f, 2.0f, 3.0f, 4.0f};
266      const vsx_float64_vec_t f64_iota1 = {1.0, 2.0};
267  
268      int num_of_tests_failed = 0;
269  
270      for (int i = 0; i < 16; i++) {
271          const vsx_int32_vec_t nan_mask = vsx_int32_vec_from_mask(i);
272          const vsx_float32_vec_t f32_v =
273              vsx_float32_logical_or(f32_iota1, (vsx_float32_vec_t)nan_mask);
274          num_of_tests_failed +=
275              (int)(!test_vsx_conv_float32_vec_to_int32_vec(f32_v));
276          num_of_tests_failed +=
277              (int)(!test_vsx_conv_float32_vec_to_int64_vec(f32_v));
278          num_of_tests_failed +=
279              (int)(!test_vsx_conv_float32_vec_to_uint32_vec(f32_v));
280          num_of_tests_failed +=
281              (int)(!test_vsx_conv_float32_vec_to_uint64_vec(f32_v));
282      }
283  
284      for (int i = 0; i < 4; i++) {
285          const vsx_int64_vec_t nan_mask = vsx_int64_vec_from_mask(i);
286          const vsx_float64_vec_t f64_v =
287              vsx_float64_logical_or(f64_iota1, (vsx_float64_vec_t)nan_mask);
288          num_of_tests_failed +=
289              (int)(!test_vsx_conv_float64_vec_to_int32_vec(f64_v));
290          num_of_tests_failed +=
291              (int)(!test_vsx_conv_float64_vec_to_int64_vec(f64_v));
292          num_of_tests_failed +=
293              (int)(!test_vsx_conv_float64_vec_to_uint32_vec(f64_v));
294          num_of_tests_failed +=
295              (int)(!test_vsx_conv_float64_vec_to_uint64_vec(f64_v));
296      }
297  
298      printf("%d tests failed\n", num_of_tests_failed);
299      return (int)(num_of_tests_failed != 0);
300  }
301