1 #include <assert.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <stdint.h> 5 #include <inttypes.h> 6 #include "opcodes.h" 7 #include "rounding.h" 8 9 /* Test "convert to fixed" with rounding mode given in insn (m3 field) 10 Covers all generally available rounding modes that can be mapped to 11 IRRoundingMode. As a consequence m3=1 which is "round to nearest with 12 ties away from 0" is not tested here. 13 */ 14 15 const char * 16 rtext(unsigned m3_round) 17 { 18 switch (m3_round) { 19 case 0: return "[-> per fpc]"; 20 case 1: return "[-> nearest away]"; 21 case 3: return "[-> prepare short]"; // floating point extension fac needed 22 case 4: return "[-> nearest even]"; 23 case 5: return "[-> 0]"; 24 case 6: return "[-> +inf]"; 25 case 7: return "[-> -inf]"; 26 } 27 assert(0); 28 } 29 30 #define convert_to_int(opcode,src_type,dst_type,dst_fmt,round,value) \ 31 do { \ 32 src_type src = value; \ 33 dst_type dst; \ 34 unsigned cc; \ 35 \ 36 __asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \ 37 "ipm %[cc]\n\t" \ 38 "srl %[cc],28\n\t" \ 39 : [dst] "=d"(dst), [cc] "=d"(cc) \ 40 : [src] "f"(src) \ 41 : "cc"); \ 42 \ 43 printf("%s %f\t-> %"dst_fmt"\tcc = %u %s\n", \ 44 opcode, src, dst, cc, rtext(round)); \ 45 } while (0) 46 47 #define round_to_int(opcode,type,round,value) \ 48 do { \ 49 type src = value; \ 50 type dst; \ 51 \ 52 __asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \ 53 : [dst] "=f"(dst) \ 54 : [src] "f"(src)); \ 55 \ 56 printf("%s %.5f\t-> %g %s\n", \ 57 opcode, src, dst, rtext(round)); \ 58 } while (0) 59 60 61 #define cfebr(value, round) \ 62 convert_to_int("cfebr",float,int32_t,PRId32,round,value) 63 #define cfdbr(value, round) \ 64 convert_to_int("cfdbr",double,int32_t,PRId32,round,value) 65 #define cgebr(value, round) \ 66 convert_to_int("cgebr",float,int64_t,PRId64,round,value) 67 #define cgdbr(value, round) \ 68 convert_to_int("cgdbr",double,int64_t,PRId64,round,value) 69 70 #define fiebr(value, round) \ 71 round_to_int("fiebr",float,round,value) 72 #define fidbr(value, round) \ 73 round_to_int("fidbr",double,round,value) 74 75 void 76 set_rounding_mode(unsigned mode) 77 { 78 register unsigned r asm("1") = mode; 79 __asm__ volatile ( SFPC(1) : : "d"(r) ); 80 } 81 82 83 int main(void) 84 { 85 int j; 86 static const float fval[] = { 87 1.25f, 1.5f, 2.5f, 1.75f, -1.25f, -1.5f, -2.5f, -1.75f, 0.0f, 88 }; 89 static const double dval[] = { 90 1.25, 1.5, 2.5, 1.75, -1.25, -1.5, -2.5, -1.75, 0.0, 91 }; 92 93 /* Note when testing M3_NEAR need to set the FPC rounding mode 94 to something else. FPC rounding mode is NEAR by default. 95 Setting the FPC rounding mode to != NEAR is the only way to make 96 sure the M3 field is not ignored. */ 97 98 /* f32 -> i32 */ 99 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) { 100 set_rounding_mode(FPC_BFP_ROUND_ZERO); 101 cfebr(fval[j], M3_BFP_ROUND_NEAREST_EVEN); 102 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN); 103 cfebr(fval[j], M3_BFP_ROUND_ZERO); 104 cfebr(fval[j], M3_BFP_ROUND_POSINF); 105 cfebr(fval[j], M3_BFP_ROUND_NEGINF); 106 } 107 108 /* f32 -> i64 */ 109 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) { 110 set_rounding_mode(FPC_BFP_ROUND_ZERO); 111 cgebr(fval[j], M3_BFP_ROUND_NEAREST_EVEN); 112 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN); 113 cgebr(fval[j], M3_BFP_ROUND_ZERO); 114 cgebr(fval[j], M3_BFP_ROUND_POSINF); 115 cgebr(fval[j], M3_BFP_ROUND_NEGINF); 116 } 117 118 /* f64 -> i32 */ 119 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { 120 set_rounding_mode(FPC_BFP_ROUND_ZERO); 121 cfdbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN); 122 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN); 123 cfdbr(dval[j], M3_BFP_ROUND_ZERO); 124 cfdbr(dval[j], M3_BFP_ROUND_POSINF); 125 cfdbr(dval[j], M3_BFP_ROUND_NEGINF); 126 } 127 128 /* f64 -> i64 */ 129 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { 130 set_rounding_mode(FPC_BFP_ROUND_ZERO); 131 cgdbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN); 132 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN); 133 cgdbr(dval[j], M3_BFP_ROUND_ZERO); 134 cgdbr(dval[j], M3_BFP_ROUND_POSINF); 135 cgdbr(dval[j], M3_BFP_ROUND_NEGINF); 136 } 137 138 /* f32 -> f32, round to int */ 139 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { 140 set_rounding_mode(FPC_BFP_ROUND_ZERO); 141 fiebr(dval[j], M3_BFP_ROUND_NEAREST_EVEN); 142 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN); 143 fiebr(dval[j], M3_BFP_ROUND_ZERO); 144 fiebr(dval[j], M3_BFP_ROUND_POSINF); 145 fiebr(dval[j], M3_BFP_ROUND_NEGINF); 146 } 147 148 /* f64 -> f64, round to int */ 149 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { 150 set_rounding_mode(FPC_BFP_ROUND_ZERO); 151 fidbr(dval[j], M3_BFP_ROUND_NEAREST_EVEN); 152 set_rounding_mode(FPC_BFP_ROUND_NEAREST_EVEN); 153 fidbr(dval[j], M3_BFP_ROUND_ZERO); 154 fidbr(dval[j], M3_BFP_ROUND_POSINF); 155 fidbr(dval[j], M3_BFP_ROUND_NEGINF); 156 } 157 158 return 0; 159 } 160