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 8 /* Test "convert to fixed" with "per fpc" rounding. 9 Covers all generally available rounding modes. 10 */ 11 12 void 13 set_rounding_mode(unsigned mode) 14 { 15 register unsigned r asm("1") = mode; 16 __asm__ volatile ( SFPC(1) : : "d"(r) ); 17 } 18 19 unsigned 20 get_rounding_mode(void) 21 { 22 unsigned fpc; 23 24 __asm__ volatile ("stfpc %0\n\t" : "=m"(fpc)); 25 26 return fpc & 0x7; 27 } 28 29 30 const char * 31 rtext(unsigned fpc_round) 32 { 33 switch (fpc_round) { 34 case 0: return "[-> near]"; 35 case 1: return "[-> zero]"; 36 case 2: return "[-> +inf]"; 37 case 3: return "[-> -inf]"; 38 } 39 assert(0); 40 } 41 42 #define convert_to_int(opcode,src_type,dst_type,dst_fmt,round,value) \ 43 do { \ 44 src_type src = value; \ 45 dst_type dst; \ 46 unsigned cc; \ 47 \ 48 __asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \ 49 "ipm %[cc]\n\t" \ 50 "srl %[cc],28\n\t" \ 51 : [dst] "=d"(dst), [cc] "=d"(cc) \ 52 : [src] "f"(src) \ 53 : "cc"); \ 54 \ 55 printf("%s %f\t-> %"dst_fmt"\tcc = %u\n", \ 56 opcode, src, dst, cc); \ 57 } while (0) 58 59 60 #define cfebr(value) \ 61 convert_to_int("cfebr",float,int32_t,PRId32,0,value) 62 #define cfdbr(value) \ 63 convert_to_int("cfdbr",double,int32_t,PRId32,0,value) 64 #define cgebr(value) \ 65 convert_to_int("cgebr",float,int64_t,PRId64,0,value) 66 #define cgdbr(value) \ 67 convert_to_int("cgdbr",double,int64_t,PRId64,0,value) 68 69 int main(void) 70 { 71 int i, j; 72 static const unsigned rmodes[] = { 0, 1, 2, 3 }; 73 static const float fval[] = { 74 1.25f, 1.5f, 2.5f, 1.75f, -1.25f, -1.5f, -2.5f, -1.75f, 0.0f, 75 }; 76 static const double dval[] = { 77 1.25, 1.5, 2.5, 1.75, -1.25, -1.5, -2.5, -1.75, 0.0, 78 }; 79 80 81 for (i = 0; i < sizeof rmodes / sizeof rmodes[0]; ++i) { 82 printf("setting rounding mode to %s\n", rtext(rmodes[i])); 83 set_rounding_mode(rmodes[i]); 84 assert(get_rounding_mode() == rmodes[i]); 85 86 /* f32 -> i32 */ 87 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) { 88 cfebr(fval[j]); 89 assert(get_rounding_mode() == rmodes[i]); 90 } 91 92 /* f32 -> i64 */ 93 for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) { 94 cgebr(fval[j]); 95 assert(get_rounding_mode() == rmodes[i]); 96 } 97 98 /* f64 -> i32 */ 99 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { 100 cfdbr(dval[j]); 101 assert(get_rounding_mode() == rmodes[i]); 102 } 103 104 /* f64 -> i64 */ 105 for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) { 106 cgdbr(dval[j]); 107 assert(get_rounding_mode() == rmodes[i]); 108 } 109 110 } 111 112 return 0; 113 } 114