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 113 int main() 114 { 115 DO_I2F(); 116 DO_F2I(); 117 118 return 0; 119 } 120