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 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 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 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 } 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 } 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 } 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 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 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 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 } 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 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 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 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 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 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 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 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 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 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